1. 目录
2. 概念
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构,即可重定义该算法的某些特定步骤。
可以理解为 用抽象类存放相同逻辑,再声明一些抽象方法来胁迫子类实现剩余的逻辑。不同的子类实现不同抽象方法,即不同的剩余逻辑。
综述,它是一种自上而下的模式,类似于企业决策,决策者制定相关流程,执行层负责具体实现。
3. 应用场景
局部场景下,实现相同,但在个别细节上略有差异。
4. 优缺点
4.1. 优点
- 实现代码复用率高
- 局部实现带来的调整,对整体影响小
4.2. 缺点
- 模板和子类的耦合性高,如要对模板中的算法骨架进行变更,会影响子类变化
5. 实现
这里用一个登录后的校验密码这个场景来举例。
public class UserService {
public final boolean verifyPassWord(String userId,String password) {
String userPassWord = getById(userId);
return userPassWord.equalsIgnoreCase(password);
}
private String getById(String userId) {
// TODO: 从数据库读取
return null;
}
}
因为数据库读取用户信息比较频繁而且属于IO操作,比较影响效率,我们很多时候把热点数据放到缓存,减少跟数据库的之间的IO操作。那用什么缓存实现?不同的场景有不同的选型,所以此处,我们只写出要缓存的定义,具体实现交由子类。
5.1. 抽象类
public abstract class UserService {
/** 校验密码
* @author <a href="https://github.com/rothschil">Sam</a>
* @date 2022/8/5-12:58
* @param userId
* @param password
* @return boolean
**/
public final boolean verifyPassWord(String userId,String password) {
String userPassWord = getById(userId);
return userPassWord.equalsIgnoreCase(password);
}
private String getById(String userId) {
// 1、getByCache
String userPassWord = getCache(userId);
// 2、缓存没有,从数据库中获取
if(StringUtils.isEmpty(userPassWord)){
userPassWord =readDb(userId);
}
// 3、写入缓存
if(StringUtils.isEmpty(userPassWord)){
putCache(userId,userPassWord);
}
return userPassWord;
}
protected abstract String getCache(String userId) ;
protected abstract String putCache(String userId,String userPassWord) ;
private String readDb(String userId) {
return "";
}
}
小结:因为声明抽象方法,所以整个类也必须声明为抽象类。 重点在 getCache(String userId)
、 putCache(String userId,String userPassWord)
,具体实现交由子类,子类具体如何实现,就由子类根据实际情况完善。
5.2. 子类实现
5.2.1. Redis实现
public class RedisService extends UserService {
private RedisClient client = RedisClient.create("redis://localhost:6379");
protected String getCache(String key) {
try (StatefulRedisConnection<String, String> connection = client.connect()) {
RedisCommands<String, String> commands = connection.sync();
return commands.get(key);
}
}
protected void putCache(String key, String value) {
try (StatefulRedisConnection<String, String> connection = client.connect()) {
RedisCommands<String, String> commands = connection.sync();
commands.set(key, value);
}
}
}
5.2.2. SpringCache站点实现
public class SpringCacheService extends UserService {
@Cacheable(key = "'key'")
protected String getCache(String key) {
}
@CachePut(key = "'key'",value = "'value'",)
protected void putCache(String key, String value) {
}
}
6. 综述
模板设计模式核心思想是:父类定义骨架,子类实现某些细节。
在某些场景下为了防止子类重写父类的骨架方法,可以在父类中对骨架方法使用 final
。对于需要子类实现的抽象方法,一般声明为 protected
,使得这些方法对外部客户端不可见。