设计模式-模板方法模式(Template Method Pattern)
模板方法模式(Template Method Pattern)
概要
记忆关键字:模板方法
定义:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。
类型:行为型
模版方法模式结构图如下:
一、涉及的角色
1. AbstractClass(抽象类)
是一个抽象模板,定义并实现了一个模板方法,代码示例如下:
1 abstract class AbstractClass { 2 3 /** 4 * 基本操作1 5 */ 6 public abstract void primitiveOperation1(); 7 8 /** 9 * 基本操作2 10 */ 11 public abstract void primitiveOperation2(); 12 13 public void TemplateMethod() { 14 primitiveOperation1(); 15 primitiveOperation2(); 16 } 17 }
2. ConcreteClass(具体实现类)
实现父类所定义的一个或多个抽象方法,代码示例如下:
1 public class ConcreteClassA extends AbstractClass { 2 @Override 3 public void primitiveOperation1() { 4 System.out.println("具体A类方法1"); 5 } 6 7 @Override 8 public void primitiveOperation2() { 9 System.out.println("具体A类方法2"); 10 } 11 } 12 13 14 public class ConcreteClassB extends AbstractClass{ 15 @Override 16 public void primitiveOperation1() { 17 System.out.println("具体B类方法1"); 18 } 19 20 @Override 21 public void primitiveOperation2() { 22 System.out.println("具体B类方法2"); 23 } 24 }
3. 客户端类
1 public class Client { 2 public static void main(String[] args) { 3 AbstractClass objA = new ConcreteClassA(); 4 AbstractClass objB = new ConcreteClassB(); 5 objA.TemplateMethod(); 6 objB.TemplateMethod(); 7 } 8 } 9 10 //运行结果 11 具体A类方法1 12 具体A类方法2 13 具体B类方法1 14 具体B类方法2
二、钩子方法
当在模板方法中某一些步骤是可选的时候,也就是该步骤不一定要执行,可以由子类来决定是否要执行,则此时就需要用上钩子。
钩子是一种被声明在抽象类中的方法,但一般来说它只是空的或者具有默认值,子类可以实现覆盖该钩子,来设置算法步骤的某一步骤是否要执行。钩子可以让子类实现算法中可选的部分,让子类能够有机会对模板方法中某些一即将发生的步骤做出反应。
还是办理业务的例子,如果来的客户是vip客户,那么他就可以不必取号,可以直接办理业务。 代码如下:
1 public abstract class AbstractBusinessHandeler { 2 3 public final void execute(){ 4 if(!isVip()){//如果顾客是vip,则不用排队 5 getRowNumber(); 6 } 7 handle(); 8 judge(); 9 } 10 11 public abstract boolean isVip();//抽象的钩子方法,由子类实现 12 13 private void getRowNumber(){ 14 System.out.println("rowNumber-00" + RandomUtils.nextInt()); 15 } 16 17 public abstract void handle(); 18 19 private void judge(){ 20 System.out.println("give a praised"); 21 } 22 }
三、模板方法模式的优缺点
1. 优点
- 使用模板方法模式可以将代码的公共行为提取,以达到复用的目的。
- 而对于特殊化的行为在子类中实现。父类的模板方法可以控制子类中的具体实现。
- 子类无需了解整体算法框架,只需实现自己的业务逻辑即可。
2. 缺点
- 子类执行的结果影响了父类的结果,这和我们平时设计习惯颠倒了,在复杂项目中,会带来阅读上的难度。
- 可能引起子类泛滥和为了继承而继承的问题
四、使用场景
1. java.util.AbstractList
2. java.util.AbstractMap
在 AbstractMap 中,提供了一些方法的实现,比如 size()、isEmpty(),这些方法构成了算法的骨架。而具体的步骤实现则由子类通过实现 entrySet() 方法来完成。
1 public abstract class AbstractMap<K,V> implements Map<K,V> { 2 //... 3 public int size() { 4 return entrySet().size(); 5 } 6 7 public boolean isEmpty() { 8 return size() == 0; 9 } 10 11 @NotNull 12 public abstract Set<Entry<K,V>> entrySet(); 13 }
3. java.io.InputStream
4. AbstractApplicationContext 类中的 refresh() 方法,其中的postProcessBeanFactory 方法和 onRefresh方法,部分代码如下:
1 protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { 2 } 3 4 protected void onRefresh() throws BeansException { 5 // For subclasses: do nothing by default. 6 }
参考链接:
https://www.cnblogs.com/54chensongxia/p/12508773.html
https://www.cnblogs.com/study-hard-forever/p/13167161.html