疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java设计模式之模板方法模式


 

   

  1.什么是模板方法模式(Template Method) 为算法的执行定义了一个统一的框架,其中的某些具体实现方法需要他在子类中去完成,每个子类所做的事情可能都不一样,而子类可以在不改变这个框架的同时去完成该算法的某个具体步骤,这就是我们所说的模板模式。

  生活中的模板:

  [code]银行办理业务,1、进门取号 2、填写单据 3、等待叫号 4、窗口办理,对于这四个规则,所有来办理业务的人都需要遵循这四种规则,但是在四个

  规则中规则2填写单据去是需要顾客填写的,因为银行他并不知道顾客具体要办理什么样的业务,所以,他只能让顾客自己去填写这样的单据,这

  样银行就是为顾客定义了一个模板。

  2.如何实现模板方法模式

  [code]1.首先需要一个抽象基类,为所有子类提供一个算法框架

  2.定义一个模板方法,封装所有子类共同遵循的算法框架

  3.将对应的步奏写入模板方法中,将所有共同方法声明为私有的或者final方法,为了隐藏实现细节

  4.将所有并不知道具体实现什么的方法设置为抽象方法,为了让他的子类去实现具体细节

  5.所有子类的具体实现

  细节:钩子方法实现:加入一个判断条件,询问用户是否需要执行该操作,提供一个默认或空的实现,让子类去选择是否挂钩,

  模板方法模式的实现要素:

  准备一个抽象类,将部分逻辑以具体方法的形式实现,然后声明一些抽象方法交由子类实现剩余逻辑,用钩子方法给予子类更大的灵活性,最后将方法汇总构成一个不可改变的模板方法。

  3.模板方法模式的特点

  优点:封装性好,、复用性好、屏蔽细节、便于维护

  缺点:继承的局限性

  4.模板方法模式在项目中的应用

  [code]1.算法或操作遵循相似的逻辑

  2.重构时,把相同的代码抽取到父类中

  3.重要、复杂的算法,核心算法设计为模板算法

  下面就通过写一个银行办理业务的模板模式:

  首先是一个抽象基类:

  BankOption.java

  [code]public abstract class BankOption {

  protected String name;

  public BankOption(String name){

  this.name = name;

  }

  public void templete(){

  //1.办理业务

  business();

  //2.填写单据

  writeBills();

  //3.等待呼叫

  callWait();

  //4.窗口办理

  windowDeal();

  }

  /**

  * 办理业务

  */

  private void business(){

  System.out.println(name + "办理业务");

  }

  /**

  * 填写单据,具体填写说明单据,让用户自己选择

  */

  protected abstract void writeBills();

  /**

  * 等待呼叫

  */

  private void callWait(){

  System.out.println(name + "等待呼叫...");

  //模拟顾客等待5秒钟

  try {

  Thread.sleep(5000);

  } catch (InterruptedException e) {

  e.printStackTrace();

  }

  //5秒后等待结束,可以办理业务了

  System.out.println("呼叫" + name + "到窗口办理业务");

  }

  /**

  * 窗口办理

  */

  private void windowDeal(){

  System.out.println(name + "窗口办理");

  System.out.println("窗口办理中...");

  //模拟在窗口办理业务时3秒钟

  try {

  Thread.sleep(3000);

  } catch (InterruptedException e) {

  e.printStackTrace();

  }

  System.out.println(name + "办理业务完成");

  }

  }

  Customer1.java

  [code]public class Customer1 extends BankOption{

  public Customer1(String name){

  super(name);

  }

  @Override

  protected void writeBills() {

  System.out.println(name + "填写汇款单据");

  }

  }

  Customer2.java

  [code]public class Customer2 extends BankOption{

  public Customer2(String name){

  super(name);

  }

  @Override

  protected void writeBills() {

  System.out.println(name + "填写存款单据");

  }

  }

  Customer3.java

  [code]public class Customer3 extends BankOption{

  public Customer3(String name){

  super(name);

  }

  @Override

  protected void writeBills() {

  System.out.println(name + "填写办理银行卡业务");

  }

  }

  Main.java测试类:

  [code] `

  public class Main {

  public static void main(String[] args) {

  BankOption c1 = new Customer1("顾客1");

  BankOption c2 = new Customer2("顾客2");

  BankOption c3 = new Customer3("顾客3");

  c1.templete();

  System.out.println(" *************************");

  c2.templete();

  System.out.println("*************************");

  c3.templete();

  }

  }

  运行结果:

  顾客1办理业务

  顾客1填写汇款单据

  顾客1等待呼叫…

  呼叫顾客1到窗口办理业务

  顾客1窗口办理

  窗口办理中…

  顾客1办理业务完成

  ‘[b]***************[/b]’

  顾客2办理业务

  顾客2填写存款单据

  顾客2等待呼叫…

  呼叫顾客2到窗口办理业务

  顾客2窗口办理

  窗口办理中…

  顾客2办理业务完成

  ‘[b]***************[/b]’

  顾客3办理业务

  顾客3填写办理银行卡业务

  顾客3等待呼叫…

  呼叫顾客3到窗口办理业务

  顾客3窗口办理

  窗口办理中…

  顾客3办理业务完成

  上就是一个简单的银行办理业务的模板方法模式,我们把所以规定了的步奏,1、3、4都写在基类中,这样很好的隐藏了实现细节,顾客只需要填写对应的单据就行了,那么我们可以通过上面的例子再改进下,来理解下上面提到的细节:钩子方法,为什么使用钩子方法呢?上面我们每个用户都模拟了等待呼叫功能,有时候如果另外一个窗口已经是空闲的,就可以直接叫用户去办理业务了,这个时候我们就可以使用钩子方法了,当钩子方法钩上的时候,也就是在本程序中表示,你可以不用等待呼叫,直接去窗口办理业务了,如果没有钩上,就表示你要继续等待,这里就模拟一下,1、3不等待,2等待。通过一下代码比较一下。

  BankOption.java中加入一个钩子方法即可

  [code]public void templete(){

  //1.办理业务

  business();

  //2.填写单据

  writeBills();

  //3.等待呼叫

  if(isWait())

  callWait();

  else

  System.out.println("不需要等待");

  //4.窗口办理

  windowDeal();

  }

  //通过加入这个方法去判断是否需要等待,当然,这里有点不符合实际,

  //因为这里是用户去实现是否等待,一般来说我们是银行来控制是否顾客等待,不过只要大家理解钩子方法是什么意思就可以了

  protected abstract boolean isWait();

  然后每个用户去添加实现钩子方法即可:

  Customer1.java

  [code]@Override

  protected boolean isWait() {

  //false表示不需要等待,直接办理窗口

  return false;

  }

  Customer2.java

  [code] @Override

  protected boolean isWait() {

  //表示需要等待

  return true;

  }

  Customer3.java

  [code]@Override

  protected boolean isWait() {

  //不需要等待

  return false;

  }

  运行结果:

  顾客1办理业务

  顾客1填写汇款单据

  不需要等待

  顾客1窗口办理

  窗口办理中…

  顾客1办理业务完成

  [b]***************[/b]’

  顾客2办理业务

  顾客2填写存款单据

  顾客2等待呼叫…

  呼叫顾客2到窗口办理业务

  顾客2窗口办理

  窗口办理中…

  顾客2办理业务完成

  [b]***************[/b]’

  顾客3办理业务

  顾客3填写办理银行卡业务

  不需要等待

  顾客3窗口办理

  窗口办理中…

  顾客3办理业务完成

  模板方法模式就介绍到这里,在我们的实际开发应用过程中,模板方法模式应用非常广泛,所以这种设计模式大家一定得掌握。