1. 模板方式模式介绍
模板方式模式定义一个操作中的算法的骨架,而把一些操作延迟到子类中。使得子类可以在不改变算法结构的前提下可以重定义该算法的特定步骤。
1.1 三类模板方式
模板方式模式,仅仅使用了java的继承机制,但是一个应用非常广泛的模式。抽象模板方法分为如下几类:
1.基本方法
基本方法也称为基本操作,由子类实现的方法,并且在模板方法中被调用
- 模板方法
模板方法可以有一个或几个,一般是一个具体的方法,也就是一个骨架,实现对基本方法的调度,完成固定的逻辑。为了防止恶意操作,一般使用final
关键字,不允许被重写。
- 钩子方法
钩子方法由抽象类声明并加以实现,但是有子类来扩展,子类可以通过扩展钩子方法来影响模板方法的逻辑。
2. 举例说明
半身人小偷偷东西来举例说明模板方式模式
2.1 定义骨架:
- [x] 抽象类
AbstractStealingMethod
- [x] 基本方法1 选目标
pickedTarget
- [x] 基本方法2 迷惑目标
confusedTarget
- [x] 基本方法3 偷取
stealTheItem
- [x] 模板方法
steal
实现基本方法的调度
/**
* 描述: 抽象模板类
*
* @author biguodong
* Create time 2018-10-31 下午4:18
**/
public abstract class AbstractStealingMethod {
private static final Logger logger = LoggerFactory.getLogger(AbstractStealingMethod.class);
/**
* 挑选目标
* @return
*/
protected abstract String pickedTarget();
/**
* 迷惑目标
* @param target
*/
protected abstract void confusedTarget(String target);
/**
* 偷取目标
* @param target
*/
protected abstract void stealTheItem(String target);
/**
* 模板方法
* 执行顺序
* 1. 挑选目标
* 2. 迷惑目标
* 3. 偷取目标
*/
public final void steal(){
String target = pickedTarget();
logger.info("选中目标 {}.", target);
confusedTarget(target);
stealTheItem(target);
}
}
2.2 偷取手段1-优雅的窃取
- [x] 继承抽象类
AbstractStealingMethod
- [x] 实现基本方法
/**
* 描述:微妙的偷取方法 实现 of {@link AbstractStealingMethod}
*
* @author biguodong
* Create time 2018-10-31 下午4:23
**/
public class SubtleStealingMethod extends AbstractStealingMethod{
private static final Logger logger = LoggerFactory.getLogger(SubtleStealingMethod.class);
/**
* 挑选目标
*
* @return
*/
@Override
protected String pickedTarget() {
return "商店老板";
}
/**
* 迷惑目标
*
* @param target
*/
@Override
protected void confusedTarget(String target) {
logger.info("泪牛满面的接近{},并抱住他", target);
}
/**
* 偷取目标
*
* @param target
*/
@Override
protected void stealTheItem(String target) {
logger.info("在靠近的同时悄悄摸取{}的钱包~", target);
}
}
2.3 偷取手段2-偷到了撒腿就跑
- [x] 继承抽象类
AbstractStealingMethod
- [x] 实现基本方法
/**
* 描述: 偷到了撒腿就跑偷取方法 实现 of {@link AbstractStealingMethod}
*
* @author biguodong
* Create time 2018-10-31 下午4:25
**/
public class HitAndRunStealingMethod extends AbstractStealingMethod{
private static final Logger logger = LoggerFactory.getLogger(HitAndRunStealingMethod.class);
/**
* 挑选目标
*
* @return
*/
@Override
protected String pickedTarget() {
return "老妖精女人";
}
/**
* 迷惑目标
*
* @param target
*/
@Override
protected void confusedTarget(String target) {
logger.info("从后面悄悄靠近{}", target);
}
/**
* 偷取目标
*
* @param target
*/
@Override
protected void stealTheItem(String target) {
logger.info("拿起手提包快速逃跑~");
}
}
2.4 半身人小偷-有多种窃取手段
- [x] 窃取手段非常多,可以灵活变换
/**
* 描述:半身人小偷使用 {@link AbstractStealingMethod} 偷东西
*
* @author biguodong
* Create time 2018-10-31 下午4:26
**/
public class HalfingThief {
private AbstractStealingMethod stealingMethod;
public HalfingThief(AbstractStealingMethod stealingMethod) {
this.stealingMethod = stealingMethod;
}
public void steal(){
stealingMethod.steal();
}
public void changeMethod(AbstractStealingMethod method){
this.stealingMethod = method;
}
}
2.5 小偷悄没声息的来了,瑟瑟发抖~~
/**
* 描述:模板方法使用类定义骨架,子类为空白部分提供实现。
*
* @author biguodong
* Create time 2018-10-31 下午4:49
**/
public class App {
public static void main(String[] args) {
HalfingThief halfingThief = new HalfingThief(new HitAndRunStealingMethod());
halfingThief.steal();
halfingThief.changeMethod(new SubtleStealingMethod());
halfingThief.steal();
}
}
2.6 我被偷了!**#¥¥?,有戝,抓小偷啊!!
- [x] 成功的小偷,两次都成功了,老司机
17:08:35.865 [main] INFO com.iluwatar.templatemethod.practice.AbstractStealingMethod - 选中目标 老妖精女人.
17:08:35.869 [main] INFO com.iluwatar.templatemethod.practice.HitAndRunStealingMethod - 从后面悄悄靠近老妖精女人
17:08:35.869 [main] INFO com.iluwatar.templatemethod.practice.HitAndRunStealingMethod - 拿起手提包快速逃跑~
17:08:35.869 [main] INFO com.iluwatar.templatemethod.practice.AbstractStealingMethod - 选中目标 商店老板.
17:08:35.869 [main] INFO com.iluwatar.templatemethod.practice.SubtleStealingMethod - 泪牛满面的接近商店老板,并抱住他
17:08:35.869 [main] INFO com.iluwatar.templatemethod.practice.SubtleStealingMethod - 在靠近的同时悄悄摸取商店老板的钱包~
2.7 添加钩子
- [x] 添加钩子方法影响小偷的成功率
3. 模板方法的总结
- 容易扩展
一般来说,抽象类中的模板方法是不易发生改变的部分,而抽象方法是容易发生变化的部分,因此通过增加实现类,一般可以很容易实现功能的扩展,符合开闭原则。
- 便于维护
对于模板方式模式来说,正是由于他们的主要逻辑相同,才使用了模板方法。如果不使用,任由这些相同的代码散乱的分散在不同的类中,维护起来是非常不方便的。
3.比较灵活
因为有钩子方法,因此,子类的实现也可以影响父类中主逻辑的运行。但是,此处违反了里氏替代原则,也会给程序带来风险。
网友评论