设计模式之模板方法模式和建造者模式

一、引言:
模板方法模式非常简单,每个人在java代码编写中都会用到,其方针图如下:
在这里插入图片描述
实际上,模板方法模式核心就是java的继承机制,父类叫做抽象模板,里面的方法分为两类:一类是基本方法,就是需要子类具体实现的方法,这类方法如果不需要过多的暴露接口,通常使用protected关键字声明,另一类就是模板方法,这类都是具体实现方法,完成固定逻辑,由父类完成,通常,在前面会加上关键字final,防止覆写。

二、 测试demo:

package com.example.javatestlib;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/* 模板为抽象类 */
abstract class HummerModel {
    /*
     * 首先,这个模型要能够被发动起来,别管是手摇发动,还是电力发动,反正
     * 是要能够发动起来,那这个实现要在实现类里了,需要子类实现的方法全部为protected
     */
    protected abstract void start();

    protected abstract void stop();

    protected abstract void alarm();

    protected abstract void engineBoom();

    /* 公共方法为final */
    final public void run() {
        this.start();

        this.engineBoom();

        if(this.isAlarm()){
            this.alarm();
        }

        this.stop();
    }
    /* 钩子方法,默认喇叭是会响的 */
    protected  boolean isAlarm(){
        return true;
    }
}

/* 子类一:覆写父类中的抽象方法 */
class HummerH1Model extends HummerModel {
    private boolean alarmFlag = true;

    protected void alarm() {
        System.out.println("悍马H1鸣笛...");
    }

    protected void engineBoom() {
        System.out.println("悍马H1引擎声音是这样的...");
    }

    protected void start() {
        System.out.println("悍马H1发动...");
    }

    protected void stop() {
        System.out.println("悍马H1停车...");
    }

    protected boolean isAlarm() {
        return this.alarmFlag;
    }

    /* 要不要响喇叭,是由客户来决定的 */
    public void setAlarm(boolean isAlarm) {
        this.alarmFlag = isAlarm;
    }
}

/* 子类二:覆写父类中的抽象方法 */
class HummerH2Model extends HummerModel {
    protected void alarm() {
        System.out.println("悍马H2鸣笛...");
    }
    protected void engineBoom() {
        System.out.println("悍马H2引擎声音是这样的...");
    }
    protected void start() {
        System.out.println("悍马H2发动...");
    }
    protected void stop() {
        System.out.println("悍马H2停车...");
    }
    /* 默认没有喇叭的 */
    protected boolean isAlarm() {
        return false;
    }
}

public class ModelDesign {
    public static void main(String[] args) throws IOException {
        System.out.println("-------H1型号悍马--------");
        System.out.println("H1型号的悍马是否需要喇叭声响?0-不需要   1-需要");
        String type=(new BufferedReader(new InputStreamReader(System.in))).readLine();
        HummerH1Model h1 = new HummerH1Model();
        if(type.equals("0")){
            h1.setAlarm(false);
        }
        h1.run();
        System.out.println("\n-------H2型号悍马--------");
        HummerH2Model h2 = new HummerH2Model();
        h2.run();
    }
}

三、建造者模式:
建造者模式方针图如下:
在这里插入图片描述
在上面的模板方法模式demo中,我们看到每一个最终的产品对象都是固定工艺顺序的,在实际生活中,需求会随时变更,那么,零件装配的不同执行顺序可能会产生不同的结果,在这种场景下,就需要使用到建造者模式了,这种模式跟模板方法的最大区别在与会创建一个建造者的抽象类,继承自该类的实现类会去实现具体的工艺顺序,为了更好的实现封装,避免上层知道下面的实现细节,通常会创建一个导演类director用于管理建造者。
建造者模式跟工厂模式有些相似,建造者模式关注的是零件类型和装配工艺(顺序),这是它与工厂方法模式最大不同的地方,建造者模式最主要的功能是基本方法的调用顺序安排,也就是这些基本方法已经实现了, 通俗地说就是零件的装配,顺序不同产生的对象也不同;而工厂方法则重点是创建,创建零件是它的主要职责,组装顺序则不是它关心的。

四、建造者demo:

package com.example.javatestlib;

import java.util.ArrayList;

/* 产品抽象类 */
abstract class CarModel {
    /* 这个参数是各个基本方法执行的顺序 */
    private ArrayList<String> sequence = new ArrayList<String>();

    protected abstract void start();

    protected abstract void stop();

    protected abstract void alarm();

    protected abstract void engineBoom();

    final public void run() {
        for(int i = 0; i < this.sequence.size(); i++){
            String actionName = this.sequence.get(i);
            if(actionName.equalsIgnoreCase("start")){
                this.start();
            }else if(actionName.equalsIgnoreCase("stop")){
                this.stop();
            }else if(actionName.equalsIgnoreCase("alarm")){
                this.alarm();
            }else if(actionName.equalsIgnoreCase("engine boom")){
                this.engineBoom();
            }
        }
    }
    final public void setSequence(ArrayList sequence){
        this.sequence = sequence;
    }
}

/* 具体产品一:奔驰车 */
class BenzModel extends CarModel {
    protected void alarm() {
        System.out.println("奔驰车的喇叭声音是这个样子的...");
    }
    protected void engineBoom() {
        System.out.println("奔驰车的引擎是这个声音的...");
    }
    protected void start() {
        System.out.println("奔驰车跑起来是这个样子的...");
    }
    protected void stop() {
        System.out.println("奔驰车应该这样停车...");
    }
}

/* 具体产品一:宝马车 */
class BMWModel extends CarModel {
    protected void alarm() {
        System.out.println("宝马车的喇叭声音是这个样子的...");
    }
    protected void engineBoom() {
        System.out.println("宝马车的引擎是这个声音的...");
    }
    protected void start() {
        System.out.println("宝马车跑起来是这个样子的...");
    }
    protected void stop() {
        System.out.println("宝马车应该这样停车...");
    }
}

/* 建造者抽象类 */
abstract class CarBuilder {
    /* 建造一个模型, 你要给我一个顺序要求, 就是组装顺序 */
    public abstract void setSequence(ArrayList<String> sequence);
    /* 设置完毕顺序后, 就可以直接拿到这个车辆模型 */
    public abstract CarModel getCarModel();
}

/* 建造者具体类:奔驰车 */
class BenzBuilder extends CarBuilder {
    private BenzModel benz = new BenzModel();
    public CarModel getCarModel() {
        return this.benz;
    }
    public void setSequence(ArrayList<String> sequence) {
        this.benz.setSequence(sequence);
    }
}

/* 建造者具体类:宝马车 */
class BMWBuilder extends CarBuilder {
    private BMWModel bmw = new BMWModel();
    public CarModel getCarModel() {
        return this.bmw;
    }
    public void setSequence(ArrayList<String> sequence) {
        this.bmw.setSequence(sequence);
    }
}

/* 导演类用于封装 */
class Director {
    private ArrayList<String> sequence = new ArrayList();
    private BenzBuilder benzBuilder = new BenzBuilder();
    private BMWBuilder bmwBuilder = new BMWBuilder();
    /**
     * A类型的奔驰车模型, 先start, 然后stop, 其他什么引擎、 喇叭一概没有
     */
    public BenzModel getABenzModel(){
        this.sequence.clear();
        this.sequence.add("start");
        this.sequence.add("stop");
        this.benzBuilder.setSequence(this.sequence);
        return (BenzModel)this.benzBuilder.getCarModel();
    }
    /**
    B型号的奔驰车模型, 是先发动引擎, 然后启动, 然后停止, 没有喇叭
    */
    public BenzModel getBBenzModel(){
        this.sequence.clear();
        this.sequence.add("engine boom");
        this.sequence.add("start");
        this.sequence.add("stop");this.benzBuilder.setSequence(this.sequence);
        return (BenzModel)this.benzBuilder.getCarModel();
    }
    /**
    C型号的宝马车是先按下喇叭(炫耀嘛) , 然后启动, 然后停止
    */
    public BMWModel getCBMWModel(){
        this.sequence.clear();
        this.sequence.add("alarm");
        this.sequence.add("start");
        this.sequence.add("stop");
        this.bmwBuilder.setSequence(this.sequence);
        return (BMWModel)this.bmwBuilder.getCarModel();
    }
    /**
    D类型的宝马车只有一个功能, 就是跑, 启动起来就跑, 永远不停止
    */
    public BMWModel getDBMWModel(){
        this.sequence.clear();
        this.sequence.add("start");
        this.bmwBuilder.setSequence(this.sequence);
        return (BMWModel)this.benzBuilder.getCarModel();
    }
}

public class BuilderDesign {
    public static void main(String[] args) {
        /* 直接创建导演类来控制建造者 */
        Director director = new Director();
        for(int i = 0; i < 2; i++){
            director.getABenzModel().run();
        }
        for(int i = 0; i < 3; i++){
            director.getBBenzModel().run();
        }
        for(int i = 0; i < 2; i++){
            director.getCBMWModel().run();
        }
    }
}

博客参考书籍:秦小波 《设计模式之禅(第2版)》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值