模板模式就是父类模板定义一个操作中算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤。
模板这种东西我们在很多地方都会有接触。比如常用的freemaker就是经典的模板,我们可以简单的理解成,我们先规定一个大的框架,相当于爸爸把儿子的路安排的明明白白,单儿子能把这条路走成什么样,就要看儿子自己的造化了。
模板模式一般分为两类 :
- 抽象父类(AbstractClass):实现了模板方法,定义了算法的骨架。
- 具体类(ConcreteClass):实现抽象类中的抽象方法,即不同的对象的具体实现细节。
========================================================================
我们还是来模拟造手机的情况,假设我们有三个手机,华为Mate40,小米11U和苹果Iphone13:
首先创建一个抽象父类:
package PrototypePattern;
/**
* @author Zeyu Wan
* @version 1.0.0
* @ClassName PhonesPrototype.java
* @Description 手机模板
* @createTime 2022年03月10日 11:09:00
*/
public abstract class PhonesPrototype {
/**
* 创建手机的方法,定义创建过程,形成模板
*/
public void makePhone(){
System.out.println("创建屏幕");
crateScreen();
System.out.println("创建处理器");
createProcessor();
System.out.println("创建电池");
createBattery();
}
/**
* 创建手机屏幕
*/
protected abstract void crateScreen();
/**
* 创建处理器
*/
protected abstract void createProcessor();
/**
* 创建电池
*/
protected abstract void createBattery();
}
抽象父类是模板模式的核心,提供了三个具体的方法由子类去实现,自己提供了一个makePhone的方法定义了抽象方法的执行顺序,并且提供了客户接入的接口。客户端不需要关系子类的具体实现流程,只需要获得造好的手机。
然后定义对应的具体类,具体类复写了抽象父类中的抽象方法,完成自己的任务:
华为:
package PrototypePattern;
/**
* @author Zeyu Wan
* @version 1.0.0
* @ClassName HuaweiP50.java
* @Description 华为手机创建
* @createTime 2022年03月10日 11:14:00
*/
public class HuaweiMate40 extends PhonesPrototype{
@Override
public void crateScreen() {
System.out.println("6.76 inch");
}
@Override
public void createProcessor() {
System.out.println("Kirin 9000");
}
@Override
public void createBattery() {
System.out.println("4400 mAh");
}
}
小米:
package PrototypePattern;
/**
* @author Zeyu Wan
* @version 1.0.0
* @ClassName Mi11U.java
* @Description 小米手机创建
* @createTime 2022年03月10日 11:11:00
*/
public class Mi11U extends PhonesPrototype{
@Override
public void crateScreen() {
System.out.println("6.81 inch AMOLED");
}
@Override
public void createProcessor() {
System.out.println("Snapdragon 888");
}
@Override
public void createBattery() {
System.out.println("5000 mAh");
}
}
苹果:
package PrototypePattern;
/**
* @author Zeyu Wan
* @version 1.0.0
* @ClassName Iphone13.java
* @Description 苹果手机创建
* @createTime 2022年03月10日 11:17:00
*/
public class Iphone13 extends PhonesPrototype{
@Override
public void crateScreen() {
System.out.println("6.1 inch");
}
@Override
public void createProcessor() {
System.out.println("A15");
}
@Override
public void createBattery() {
System.out.println("3095mAh");
}
}
每一个子类只做子类需要完成的内容,而不需要关心其他逻辑。具体的调用顺序在父类中已经规划好了,相当于专人做专事,父类考虑流程,子类考虑方法的实现。
测试一下:
package PrototypePattern;
/**
* @author Zeyu Wan
* @version 1.0.0
* @ClassName PrototypePatternTest.java
* @Description 测试类
* @createTime 2022年03月10日 11:20:00
*/
public class PrototypePatternTest {
public static void main(String[] args) {
PhonesPrototype mi11U = new Mi11U();
mi11U.makePhone();
System.out.println("--------------------------");
}
}
优点:
- 具体细节步骤实现定义在子类中,子类定义详细处理算法是不会改变算法整体结构。
- 代码复用的基本技术,在数据库设计中尤为重要。
- 存在一种反向的控制结构,通过一个父类调用其子类的操作,通过子类对父类进行扩展增加新的行为,符合“开闭原则”。
缺点:
- 每个不同的实现都需要定义一个子类,会导致类的个数增加,系统更加庞大。