模版方法模式
模板方法模式的定义如下:定义一个操作中算法的框架,而将一些步骤的实现延迟到子类中,使得子类可以不改变一个算法的结构即可重新定义某些算法的特定步骤。
而实际上我们经常使用这个模式或者用到过却没发现,比如Spring框架、并发包的队列同步器AQS等都用到了这个模式。
接下来举个例子说明一下,我想了半天最终决定举一个装机的例子吧,算是比较符合了。
/** * @author morph */ public class ComputerDemo1 extends AssembleComputerTemplate{ @Override protected void assembleCPU() { System.out.println("CPU: I9 9900k"); } @Override protected void assembleMemory() { System.out.println("Memory: 64G"); } @Override protected void assemblePower() { System.out.println("Power: 1200w"); } @Override protected void assembleGraphicsCard() { System.out.println("Gpu: 2080Ti"); } @Override protected void assembleMotherBoard() { System.out.println("MotherBoard: ROG MM XI APEX"); } @Override protected void assembleCase() { System.out.println("Case: shoebox"); } public static void main(String[] args) { AssembleComputerTemplate computer = new ComputerDemo1(); computer.startUp(); } }
打印结果如下:
再装个机子二号:
/** * @author morph */ public class ComputerDemo2 extends AssembleComputerTemplate{ @Override protected void assembleCPU() { System.out.println("CPU: I3 5400"); } @Override protected void assembleMemory() { System.out.println("Memory: 4G"); } @Override protected void assemblePower() { System.out.println("Power: 350w"); } @Override protected void assembleGraphicsCard() {
System.out.println("Intel HD");
} @Override protected void assembleMotherBoard() { System.out.println("H310"); } @Override protected void assembleCase() { System.out.println("Case: ROG"); } //不装显卡 protected boolean isGraphicsCard(){ return false; } public static void main(String[] args) { AssembleComputerTemplate computer = new ComputerDemo2(); computer.startUp(); } }
打印结果如下:
可以看到代码中的钩子函数可以控制公共流程,而且每个机子的组件都由子类自己实现扩展,但是公共方法由父类定义,这就是一个简单的模版方法设计模式。此处注意为了防止恶意操作,父类的模版方法需要用final修饰,不允许重写。
模版方法模式的优点:
封装不可变部分,扩展可变部分。所谓封装不可变,是指将不可变的步骤方法封装到父类实现,而扩展可变是指将可变的方法通过继承来扩展。
提取公共代码,便于维护。
行为由父类控制,子类实现。
缺点:因为在模版方法设计模式中,抽象类定义了部分抽象方法,由子类实现,这样子类会对父类产生影响,会降低代码可读性。
使用场景
多个子类有公有的方法,逻辑基本相同。
核心算法可以设计为模版方法,周边的细节功能由子类实现。
重构时,可以将相同代码封装到父类中,然后通过钩子函数约束其行为。