首页 > 代码库 > 设计模式之禅-模板方法模式
设计模式之禅-模板方法模式
个人Blog 此篇博文所在地址:http://www.sanyinchenblog.com/?p=273
模板方法模式:
定义一个操作中的算法框架,将一些步骤延迟到子类中。使得子类可以不改变 一个算法的结构即可重定义该算法的某些特定步骤。
Demo:
https://github.com/sanyinchen/UMLDemo/tree/master/src/com/sanyinchen/templete
https://github.com/sanyinchen/UMLDemo/tree/master/src/com/sanyinchen/templete2
介绍一下书上的背景,大概的背景是要做一个车的模型。
类图是这样的:
Client类:
package com.sanyinchen.templete; public class Client { public static void main(String[] args) { // TODO Auto-generated method stub HummerModel hummerModel = new HummerH1Model1(); hummerModel.start(); hummerModel.engineBoom(); hummerModel.alarm(); hummerModel.run(); System.out.println("--------------------"); hummerModel = new HummerH1Model2(); hummerModel.start(); hummerModel.engineBoom(); hummerModel.alarm(); hummerModel.run(); } }
HummerModel:
public abstract class HummerModel { public abstract void start(); public abstract void stop(); public abstract void alarm();// 喇叭鸣叫 public abstract void engineBoom();// 引擎发出轰鸣声 public abstract void run(); }
HummerH1Model1
package com.sanyinchen.templete; public class HummerH1Model1 extends HummerModel { @Override public void start() { // TODO Auto-generated method stub System.out.println("HummerH1Model1启动了"); } @Override public void stop() { // TODO Auto-generated method stub System.out.println("HummerH1Model1停止了"); } @Override public void alarm() { // TODO Auto-generated method stub System.out.println("HummerH1Model1喇叭叫了"); } @Override public void engineBoom() { // TODO Auto-generated method stub System.out.println("HummerH1Model1引擎启动了"); } @Override public void run() { // TODO Auto-generated method stub System.out.println("HummerH1Model1跑起来了"); } }
HummerH1Model2
public class HummerH1Model2 extends HummerModel { @Override public void start() { // TODO Auto-generated method stub System.out.println("HummerH1Model2启动了"); } @Override public void stop() { // TODO Auto-generated method stub System.out.println("HummerH1Model2停止了"); } @Override public void alarm() { // TODO Auto-generated method stub System.out.println("HummerH1Model2喇叭叫了"); } @Override public void engineBoom() { // TODO Auto-generated method stub System.out.println("HummerH1Model2引擎启动了"); } @Override public void run() { // TODO Auto-generated method stub System.out.println("HummerH1Model2跑起来了"); } }程序运行的结构:
HummerH1Model1启动了 HummerH1Model1引擎启动了 HummerH1Model1喇叭叫了 HummerH1Model1跑起来了 -------------------- HummerH1Model2启动了 HummerH1Model2引擎启动了 HummerH1Model2喇叭叫了 HummerH1Model2跑起来了当然,我们可以将每一步封装在run方法里:
HummerH1Model3:
package com.sanyinchen.templete; public class HummerH1Model3 extends HummerModel { @Override public void start() { // TODO Auto-generated method stub System.out.println("HummerH1Model3启动了"); } @Override public void stop() { // TODO Auto-generated method stub System.out.println("HummerH1Model3停止了"); } @Override public void alarm() { // TODO Auto-generated method stub System.out.println("HummerH1Model3喇叭叫了"); } @Override public void engineBoom() { // TODO Auto-generated method stub System.out.println("HummerH1Model3引擎启动了"); } @Override public void run() { // TODO Auto-generated method stub this.start(); this.engineBoom(); this.alarm(); System.out.println("HummerH1Model3跑起来了"); } }这就是一个基本的模板设计模式,但是我们明显的可以看到会有重复代码,如果按照model3那个方式来,那么model4呢?run()里面的方法是一样的。
所以我们可以将HummerModel里的方法变为实现方法,所以在其他model继承的它的时候自然不需要再次实现它。
模板方法的优点:
(1)封装不变部分,扩展可变部分
(2)提取公共部分代码,便于维护
(3)行为由父类控制,子类实现
模板方法模式使用场景:
(1)多个子类有公有的方法,并且逻辑基本相同
(2)重要,复杂的代码,可以把核心算法设计为模板方法,周边相关细节功能则由各个子类实现
(3)重构时,模板方法模式是一个经常使用的模式,把相同的代码抽到父类中,然后通过钩子函数约束其行为。
模板方法的扩展:
下面需要修改一下需求,model1和model2的喇叭响不响是有控制的,因此添加一个钩子函数。
修改之后的类图:
Client
package com.sanyinchen.templete2; /** * 模板方法模式 钩子函数使用 * * @author sanyinchen * */ public class Client { public static void main(String[] args) { // TODO Auto-generated method stub HummerModel hummerModel = new HummerH1Model1(); hummerModel.run(); System.out.println("--------------------"); hummerModel = new HummerH1Model2(); hummerModel.run(); System.out.println("--------------------"); HummerH1Model3 hummerMode3 = new HummerH1Model3(); hummerMode3.steAram(false); hummerMode3.run(); } }
HummerModel:
package com.sanyinchen.templete2; public abstract class HummerModel { public abstract void start(); public abstract void stop(); public abstract void alarm();// 喇叭鸣叫 public abstract void engineBoom();// 引擎发出轰鸣声 public abstract boolean isAlarm(); public void run() { // TODO Auto-generated method stub this.start(); this.engineBoom(); this.alarm(); } }
HummerH1Model3
package com.sanyinchen.templete2; public class HummerH1Model3 extends HummerModel { private boolean isArm = true; @Override public void start() { // TODO Auto-generated method stub System.out.println("HummerH1Model3启动了"); } @Override public void stop() { // TODO Auto-generated method stub System.out.println("HummerH1Model3停止了"); } @Override public void alarm() { // TODO Auto-generated method stub if(this.isAlarm()) System.out.println("HummerH1Model3喇叭叫了"); } @Override public void engineBoom() { // TODO Auto-generated method stub System.out.println("HummerH1Model3引擎启动了"); } @Override public boolean isAlarm() { // TODO Auto-generated method stub return this.isArm; } public void steAram(boolean flag) { this.isArm = flag; } }
运行结果:
HummerH1Model1启动了 HummerH1Model1引擎启动了 HummerH1Model1喇叭叫了 -------------------- HummerH1Model2启动了 HummerH1Model2引擎启动了 HummerH1Model2喇叭叫了 -------------------- HummerH1Model3启动了 HummerH1Model3引擎启动了
由此可以看出model3要不要响喇叭是由场景类决定的。
设计模式之禅-模板方法模式