Java设计模式之模板模式详解

模板模式


在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。

**主要解决:**一些方法通用,却在每一个子类都重新写了这一方法。

注意:

  1. 父类必须是抽象类

  2. 模板方法或者叫公共逻辑方法必须用final修饰 ,如:play()

    ​ 保证其不会被子类修改

  3. 子方法必须是抽象,如endPlay()

  4. 可以添加一个protect 表明其需要在子类中实现

    因为protect可以在同一个类,同一个包,不同包的子类也可以访问到

public abstract class Game {
   abstract void initialize();
    //可以添加一个protect 表明其需要在子类中实现
   //protected abstract void initialize();
   abstract void startPlay();
   abstract void endPlay();
 
   //模板,即公共逻辑
   public final void play(){
 
      //初始化游戏
      initialize();
 
      //开始游戏
      startPlay();
 
      //结束游戏
      endPlay();
   }
}

子类

package moshi.moban;

public class BasBall extends Game {
    @Override
    void initialize() {
        System.out.println("BasBall start ");
    }

    @Override
    void startPlay() {
        System.out.println("BasBall start ");
    }

    @Override
    void endPlay() {
        System.out.println("BasBall start ");
    }
}

package moshi.moban;

public class Football extends Game {
    @Override
    void initialize() {
        System.out.println("football init ");
    }

    @Override
    void startPlay() {
        System.out.println("football start ");
    }

    @Override
    void endPlay() {
        System.out.println("football end ");
    }

    public static void main(String[] args) {
        Game football =new Football();
        football.play();
        System.out.println();
        football=new BasBall();
        football.play();

    }
}

结果:

football init 
football start 
football end 

BasBall start 
BasBall start 
BasBall start 

其实,模板模式中还有一个钩子方法的概念,有人称,具有钩子方法的模板模式才算完整,也许吧。

钩子方法时干啥的呢?钩子就是给子类一个授权,允许子类通过重写钩子方法来颠覆基本逻辑的执行,这有时候是非常有用的。就比如在盖房子的时候,有一个需要子类来决定是否建造厕所间的需求时,可以这么实现:

public abstract class HouseTemplate {

    protected HouseTemplate(String name){
        this.name = name;
    }

    protected String name;

    protected abstract void buildDoor();

    protected abstract void buildWindow();

    protected abstract void buildWall();

    protected abstract void buildBase();

    protected abstract void buildToilet();

    //钩子方法
    protected boolean isBuildToilet(){
        return true;
    }

    //公共逻辑
    public final void buildHouse(){

        buildBase();
        buildWall();
        buildDoor();
        buildWindow();
        if(isBuildToilet()){
            buildToilet();
        }
    }

}

子类一:要实现建厕所

public class HouseOne extends HouseTemplate {

    HouseOne(String name){
        super(name);
    }

    HouseOne(String name, boolean isBuildToilet){
        this(name);
        this.isBuildToilet = isBuildToilet;
    }

    public boolean isBuildToilet;

    @Override
    protected void buildDoor() {
        System.out.println(name +"的门要采用防盗门");
    }

    @Override
    protected void buildWindow() {
        System.out.println(name + "的窗户要面向北方");
    }

    @Override
    protected void buildWall() {
        System.out.println(name + "的墙使用大理石建造");
    }

    @Override
    protected void buildBase() {
        System.out.println(name + "的地基使用钢铁地基");
    }

    @Override
    protected void buildToilet() {
        System.out.println(name + "的厕所建在东南角");
    }

    @Override
    protected boolean isBuildToilet(){
        return isBuildToilet;
    }

}

子类二:不要要建厕所

public class HouseTwo extends HouseTemplate {

    HouseTwo(String name){
        super(name);
    }

    @Override
    protected void buildDoor() {
        System.out.println(name + "的门采用木门");
    }

    @Override
    protected void buildWindow() {
        System.out.println(name + "的窗户要向南");
    }

    @Override
    protected void buildWall() {
        System.out.println(name + "的墙使用玻璃制造");
    }

    @Override
    protected void buildBase() {
        System.out.println(name + "的地基使用花岗岩");
    }

    @Override
    protected void buildToilet() {
        System.out.println(name + "的厕所建在西北角");
    }

}

测试类

public class Clienter {

    public static void main(String[] args){
        HouseTemplate houseOne = new HouseOne("房子1", false);
        HouseTemplate houseTwo = new HouseTwo("房子2");
        houseOne.buildHouse();
        houseTwo.buildHouse();
    }

}

结果:

房子1的地基使用钢铁地基
房子1的墙使用大理石建造
房子1的门要采用防盗门
房子1的窗户要面向北方
房子2的地基使用花岗岩
房子2的墙使用玻璃制造
房子2的门采用木门
房子2的窗户要向南
房子2的厕所建在西北角

执行结果

猜你喜欢

转载自blog.csdn.net/qq_39455116/article/details/88018958