代码改变世界

模板模式

2017-08-17 17:27  grows  阅读(245)  评论(0编辑  收藏  举报
  1. 模板模式

模板模式:即提供一个统一的模板算法(执行每个方法的顺序,以及那一部分需要执行,那一部分不需要执行),而其中需要频繁变化的部分设计为抽象的,而固定不变的部分设计具体的方法,如果需要改变模板中的某个流程,则使用钩子方法。

       其是基于继承的代码复用技术

  1. 角色

1) 抽象类:用于设计具体的模板(包括四种方法)

  1. 具体方法:写业务逻辑中不变的部分
  2. 抽象方法:写需要根据逻辑方法变化的部分
  3. 钩子方法:想要改变模板方法中方法执行流程的部分,
  4. 模板方法:根据业务逻辑具体的执行流程,一般设计为final 类型以防止被重写

2) 具体类:实现抽象类中的某个抽象方法,需要变化的,或者重写具体方法,或者重写控制算法流程的钩子方法

  1. 特别分析:

钩子方法通常设计为具体的没有任何实现的类或者是返回true的方法,用来控制模板方法中的流程

  1. 代码实现

例如:我们种花的时候一般分为:(买盆 or 不买盆)——选择花——装土——浇水

       分析:

1) 如果要是直接种到土地里面买盆就不是必须的,如果种到花盆中则需要买,所以这里有个判断的过程(这时候我们需要把用一个钩子方法,用子类控制是否买盆,或者采用默认的形式),

2) 选择哪种花是不固定的,需要具体的子类来实现买什么样子的花

3) 装土是固定的

4) 浇水也是必须的

抽象方法:种花

 

package templatemodel;

public  abstract class PlantFlowers {
    /**
     * 钩子方法,用来控制模板方法中的流程
     * @return
     */
    public boolean isBuyBasin(){
        return true;
    }
    /**
     * 买盆,固定方法不会发生变化,根据需要判断是否调用
     */
    public void buyBasin(){
        System.out.println("买盆。。。");
    }
    /**
     * 选择花的类型,不固定,让子类去实现具体选哪种花
     */
    public abstract void choseFlower();
    /**
     * 装土,固定方法不会发生变化,但是也可以让子类重写
     */
    public void useSoil()
    {
        System.out.println("装土。。。。");
    }
    /**
     * 浇水,固定方法不会发生变化,但是也可以让子类重写
     */
    public void useWater()
    {
        System.out.println("浇水。。。。");
    }
    /**
     * 模板方法,用于具体的流程
     */
  public void proccess(){
      if(this.isBuyBasin()){
          buyBasin();//买盆
      }
      choseFlower();//选花
      useSoil();//装土
      useWater();//浇水
      
  }
}

 

 

具体实现类:选择玫瑰

package templatemodel;

/**
 * 选择玫瑰花,采用默认流程即在花盆中种花
 * @author Administrator
 *
 */
public class ChoseRose extends PlantFlowers {

    @Override
    public void choseFlower() {
        // TODO Auto-generated method stub
        System.out.println("选择玫瑰花。。");
    }

}

 

 

具体实现类:选择牡丹

package templatemodel;

/**
 * 选择牡丹花,改变钩子方法,即直接在土地上种花
 * @author Administrator
 *
 */
public class ChosePeony extends PlantFlowers {

    @Override
    public void choseFlower() {
        // TODO Auto-generated method stub
        System.out.println("选择牡丹花。。");
    }
    @Override
    public boolean isBuyBasin(){
        return false;
    }

}

 

 

      测试类:

package templatemodel;

public class TestTemplate {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //种玫瑰花
        PlantFlowers plantRose=new ChoseRose();
        plantRose.proccess();
        System.out.println();
        //种牡丹花
        PlantFlowers plantPeony=new ChosePeony();
        plantPeony.proccess();
    }

}

 

 

结果:

 

买盆。。。
选择玫瑰花。。
装土。。。。
浇水。。。。

选择牡丹花。。
装土。。。。
浇水。。。。
  1. 优点

1) 形成一个固定的算法流程具体细节可以由子类去实现,可以是整体保持不变

2) 代码复用,不用去写很多的重复流程,尤其是对于流程固定的场景

  1. 缺点(感觉优点牵强)

1)不同的实现需要不同子类,如果由大量的实现会导致子类很多

  1. 场景

1) 大致流程固定,具体的实现想要根据具体的场景在去实现

2) 需要分割复杂的算法,分离出固定的部分和变化的部分,把变化的设计为抽象,具体是由子类去实现,

3) 通过子类来决定是否去改变父类中的流程