建造者模式

目录

1.变化是永恒的

2. 建造者模式的应用

2.1 优点

2.2 使用场景


1.变化是永恒的

在模板方法模式中,我们的模板方法是按照固定的顺序进行执行的。假如我们顺序是可以调整的,有些方法可能执行,有些方法可能不执行,又该如何设计呢?我们以制造汽车的过程为例,假如汽车形式分为启动、停止、鸣喇叭和引擎声等几个过程,而不同品牌的汽车,执行过程又不尽相同,此时我们可以在汽车模型类CarModel中定义一个setSequence方法,车辆模型的这几个动作如何排布,是定义在这个ArrayList中的,然后run()方法根据sequence定义的顺序完成指定的顺序动作。CarModel的源代码定义如下:

import java.util.ArrayList;
import java.util.List;

/**
 * @author: martin
 * @date: 2019/9/22 20:38
 * @description:
 */
public abstract class CarModel {
    //存放各个基本方法执行的顺序
    private List<String> sequence = new ArrayList<>();

    //启动开始跑
    protected abstract void start();

    //停下来
    protected abstract void stop();

    //喇叭鸣笛
    protected abstract void alarm();

    //引擎轰轰响
    protected abstract void engineBoom();

    //汽车运行
    public final void run() {
        for (String actionName : sequence) {
            if (actionName.equals("start")) {
                this.start();
            } else if (actionName.equals("stop")) {
                this.stop();
            } else if (actionName.equals("alarm")) {
                this.alarm();
            } else if (actionName.equals("engine")) {
                this.engineBoom();
            }
        }
    }

    protected void setSequence(List<String> sequence) {
        this.sequence = sequence;
    }
}

CarModel的设计原理是这样的,setSequence方法允许客户自己设置一个顺序。因此,对于一个具体的模型永远都是固定的,但是对N多个模型个模型就是动态的了。在子类中实现父类的基本方法,run()方法读取sequence,然后遍历sequence中的字符串,哪个字符串在前,就先执行哪个方法。

奔驰模型代码:

public class BenzModel extends CarModel {
    @Override
    protected void start() {
        System.out.println("奔驰车启动");
    }

    @Override
    protected void stop() {
        System.out.println("奔驰车停车");
    }

    @Override
    protected void alarm() {
        System.out.println("奔驰车鸣笛");
    }

    @Override
    protected void engineBoom() {
        System.out.println("奔驰车引擎");
    }
}

宝马模型:

public class BMWModel extends CarModel {
    @Override
    protected void start() {
        System.out.println("宝马车启动");
    }

    @Override
    protected void stop() {
        System.out.println("宝马车停车");
    }

    @Override
    protected void alarm() {
        System.out.println("宝马车鸣笛");
    }

    @Override
    protected void engineBoom() {
        System.out.println("宝马车引擎");
    }
}

两个产品的实现类都完成了,我们来模拟一下生产的过程:

public class Client {
    public static void main(String[] args) {
        BenzModel benzModel = new BenzModel();
        List<String> sequence = new ArrayList<>();
        sequence.add("engine");
        sequence.add("start");
        sequence.add("stop");
        benzModel.setSequence(sequence);

        benzModel.run();
    }
}

输出结果为:

奔驰车引擎
奔驰车启动
奔驰车停车

这样我们就组装了一辆奔驰车。但是按照现在的设计方法,假如我们再要一个宝马模型只要启动和停止,其他的都不要,我们就需要在场景类Client中创建sequence,然后再run。如果又有新的模型,我们就一个一个地来写场景类来满足吗?为了解决这种无休止的新增代码,我们可以为每一种模型产品定义一个建造者,需要什么样的顺序直接告诉建造者,由建造者来建造,实现的类图如下:

上图中增加了一个CarBuilder抽象类,由它来组装各个车模,要什么类型什么顺序的车辆模型都由相关的子类完成。代码如下:

public abstract class CarBuilder {
    //建造一个模型的组装顺序
    public abstract void setSequence(ArrayList<String> sequence);

    //顺序设置完成后,就可以直接拿到车辆模型
    public abstract CarModel getCarModel();
}

public class BenzBuilder extends CarBuilder {
    private BenzModel benzModel = new BenzModel();
    @Override
    public void setSequence(ArrayList<String> sequence) {
        this.benzModel.setSequence(sequence);
    }

    @Override
    public CarModel getCarModel() {
        return this.benzModel;
    }
}

public class BMWBuilder extends CarBuilder {
    private BMWModel bmwModel = new BMWModel();

    @Override
    public void setSequence(ArrayList<String> sequence) {
        this.bmwModel.setSequence(sequence);
    }

    @Override
    public CarModel getCarModel() {
        return this.bmwModel;
    }
}

场景类实现如下:

public class Client {
    public static void main(String[] args) {
        ArrayList<String> sequence = new ArrayList<>();
        sequence.add("engine");
        sequence.add("start");
        sequence.add("stop");

        BenzBuilder benzBuilder = new BenzBuilder();
        benzBuilder.setSequence(sequence);
        BenzModel benzModel = (BenzModel) benzBuilder.getCarModel();
        benzModel.run();

        BMWBuilder bmwBuilder = new BMWBuilder();
        bmwBuilder.setSequence(sequence);
        BMWModel bmwModel = (BMWModel) bmwBuilder.getCarModel();
        bmwModel.run();
    }
}


奔驰车引擎
奔驰车启动
奔驰车停车
宝马车引擎
宝马车启动
宝马车停车

这样我们就可以生产出相同顺序的宝马车和奔驰车了,实现的代码也比直接访问产品类简单了很多。

建造者模式也叫做生成器模式,定义如下:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

2. 建造者模式的应用

2.1 优点

  • 封装性:使用建造者模式可以使得客户端不必知道产品内部组成的细节。
  • 建造者独立,容易扩展:BenzBuilder和BMWBuilder是相互独立的,对系统的扩展非常有利。
  • 便于控制细节:由于具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何影响。

2.2 使用场景

  • 相同的方法,不同的执行顺序,产生不同的事件结果时,可以采用建造者模式。
  • 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果有不相同时,则可以使用该模式。
  • 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式非常合适。

建造者模式最主要的功能是基本方法调用顺序的安排,也就是这些基本方法已经实现了,关注的是零件类型和装配工艺(顺序)。而工厂方法则重点是创建,创建零件是它的主要职责,组装顺序则不是它关心的。两者虽然同为创建类模式,但是注重点不同。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
内容简介: 设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。 本课程内容定位学习设计原则,学习设计模式的基础。在实际开发过程中,并不是一定要求所有代码都遵循设计原则,我们要考虑人力、时间、成本、质量,不是刻意追求完美,要在适当的场景遵循设计原则,体现的是一种平衡取舍,帮助我们设计出更加优雅的代码结构。本章将详细介绍开闭原则(OCP)、依赖倒置原则(DIP)、单一职责原则(SRP)、接口隔离原则(ISP)、迪米特法则(LoD)、里氏替换原则(LSP)、合成复用原则(CARP)的具体内容。 为什么需要学习这门课程? 你在日常的开发中,会不会也遇到过同样的问题。系统出现问题,不知道问题究竟出在什么位置;当遇到产品需求,总是对代码缝缝补补,不能很快的去解决。而且平时工作中,总喜欢把代码堆在一起,出现问题时,不知道如何下手,工作效率很低,而且自己的能力也得不到提升。而这些都源于一个问题,那就是软件设计没做好。这门课能帮助你很好的认识设计模式,让你的能力得到提升。课程大纲: 为了让大家快速系统了解设计模式知识全貌,我为您总结了思维导图,帮您梳理学习重点,建议收藏!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值