前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【设计模式】第四篇:建造者模式也没那么难

【设计模式】第四篇:建造者模式也没那么难

作者头像
BWH_Steven
发布2020-11-10 14:08:22
2370
发布2020-11-10 14:08:22
举报
文章被收录于专栏:理想二旬不止理想二旬不止

一 引言

说明:如果想要直接阅读定义等理论内容,可以直接跳转到第二大点

在生活中有很多场景与我们今天要说的 “建造者模式” 是非常匹配的,打个比方一台计算机是由 CPU、内存、显卡、内存、鼠标、键盘、显示器等等内容组合而成的,我们想要一台电脑,我们不会可能自己去做这些配件,一般都是通过告诉销售公司,然后其派生产技术人员给你做好指定的配件。

先不管,谁买,谁做,谁管理的问题,我们可以分析得到,建造电脑的这个 “过程” 是稳定的也就是说,不管什么配置的电脑,这些配件都是必须要有的,只是具体的细节不一样,例如你的配置更好,他的差一些

但是,我作为一个买家,我并不想管这些,我只告诉你,我要一台中等配置的电脑,你负责“建造”好给我就行了,这就是建造者模式比较通俗的讲法

下面我们通过这个计算机的例子,循序渐进的看一下:

二 通过例子循序渐进认识建造者模式

首先,不管怎么建,怎么买,一个 Computer 电脑类是必须的,我们随便挑选三个组件来进行演示,CPU、内存、显示器,补充其 get set toString 方法

代码语言:javascript
复制
/**
 * 产品:电脑
 */
public class Computer {
    private String cpu; // CPU
    private String graphicsCard; // 内存
    private String displayScreen; // 显示器

    public String getCpu() {
        return cpu;
    }

    public void setCpu(String cpu) {
        this.cpu = cpu;
    }

    public String getGraphicsCard() {
        return graphicsCard;
    }

    public void setGraphicsCard(String graphicsCard) {
        this.graphicsCard = graphicsCard;
    }

    public String getDisplayScreen() {
        return displayScreen;
    }

    public void setDisplayScreen(String displayScreen) {
        this.displayScreen = displayScreen;
    }

    @Override
    public String toString() {
        return "Computer{" +
                "cpu='" + cpu + '\'' +
                ", graphicsCard='" + graphicsCard + '\'' +
                ", displayScreen='" + displayScreen + '\'' +
                '}';
    }
}

(一) 最简单直白的方式(不好)

这种方法基本可以说没什么技术含量了,直接 new + set 就行了

代码语言:javascript
复制
public class Test {
    public static void main(String[] args) {
        Computer computer = new Computer();
        computer.setCpu("英特尔酷睿 i5 处理器");
        computer.setGraphicsCard("4g内存");
        computer.setDisplayScreen("14寸 1080p 60hz显示器");
        System.out.println(computer.toString());
    }
}

打印一下结果:

Computer{cpu='英特尔酷睿 i5 处理器', graphicsCard='4g', displayScreen='14寸 1080p 60hz显示器'}

(二) 客户直接联系生产技术人员

上面这种方式,不用说也知道不合适了,所以技术人员(建造者)他来了!但是不同的技术人员会制作的配件也不一样,例如有的会做 144hz 的显示器,而有的专攻 60hz 的显示器,有高低配置,不同型号之分

为此我们为其抽象出一个 ComputerBuilder 的抽象类

代码语言:javascript
复制
/**
 * 电脑的建造者
 */
public abstract class ComputerBuilder {
    abstract void buildCpu(); // 建造CPU
    abstract void buildGraphicsCard(); // 建造内存
    abstract void buildDisplayScreen(); // 建造显示器

    abstract Computer getComputer(); // 拿到这台电脑
}

下面就来写建造者的具体实现,例如先写一个低配置电脑建造的实现

代码语言:javascript
复制
/**
 * 低配置电脑
 */
public class LowConfigurationComputerBuilder extends ComputerBuilder {

    private Computer computer;

    public LowConfigurationComputerBuilder(){
        computer = new Computer();
    }

    @Override
    void buildCpu() {
        computer.setCpu("英特尔酷睿 i5 处理器");
        System.out.println("buildCpu: 英特尔酷睿 i5 处理器");
    }

    @Override
    void buildGraphicsCard() {
        computer.setGraphicsCard("8g内存");
        System.out.println("buildGraphicsCard: 8g内存");
    }

    @Override
    void buildDisplayScreen() {
        computer.setDisplayScreen("1080p 60hz显示器");
        System.out.println("buildDisplayScreen: 1080p 60hz显示器");
    }

    @Override
    Computer getComputer() {
        return computer;
    }
}

测试一下:

代码语言:javascript
复制
public class Test {
    public static void main(String[] args) {
        // 创建低配置电脑建造者
        LowConfigurationComputerBuilder builder = new LowConfigurationComputerBuilder();
        builder.buildCpu();
        builder.buildGraphicsCard();
        builder.buildDisplayScreen();
        Computer computer = builder.getComputer();
        System.out.println("建造出的电脑: " + computer );
    }
}

执行结果:

buildCpu: 英特尔酷睿 i5 处理器 buildGraphicsCard: 8g内存 buildDisplayScreen: 1080p 60hz显示器 建造出的电脑: Computer{cpu='英特尔酷睿 i5 处理器', graphicsCard='8g内存', displayScreen='1080p 60hz显示器'}

(三) 客户联系销售公司

虽然上面的方法是比第一种强一些,但是客户自己去联系生产技术人员,显然不是很合理,正常的做法,我们都是先去联系销售公司,告诉他们我想要什么配置的电脑就可以了,细节我并不想管

代码语言:javascript
复制
public class SalesCompany {
    public Computer buildComputer(ComputerBuilder builder){
        builder.buildCpu();
        builder.buildGraphicsCard();
        builder.buildDisplayScreen();
        return builder.getComputer();
    }
}

测试代码

代码语言:javascript
复制
public class Test {
    public static void main(String[] args) {
        // 创建低配置电脑建造者
        LowConfigurationComputerBuilder builder = new LowConfigurationComputerBuilder();
        // 创建电脑销售中心
        SalesCompany salesCompany = new SalesCompany();
        // 指定具体的电脑建造者去完成 电脑 这个产品
        Computer computer = salesCompany.buildComputer(builder);
        System.out.println("建造出的电脑: " + computer );
    }
}

现在代码已经比较完善了,也就是我们买家通过联系电脑销售中心,然后销售中心去调用用户想要的配置的建造者,刚才我们创建的是一个“低配置电脑建造者”,如果我们想要换成中等配置的电脑,该怎么做呢?

现在只需要增加一个中等配置电脑建造者,实现Builder抽象类就可以了

代码语言:javascript
复制
/**
 * 低配置电脑
 */
public class MiddleConfigurationComputerBuilder extends ComputerBuilder {

    private Computer computer;

    public MiddleConfigurationComputerBuilder(){
        computer = new Computer();
    }

    @Override
    void buildCpu() {
        computer.setCpu("英特尔酷睿 i7 处理器");
        System.out.println("buildCpu: 英特尔酷睿 i7 处理器");
    }

    @Override
    void buildGraphicsCard() {
        computer.setGraphicsCard("16g内存");
        System.out.println("buildGraphicsCard: 16g内存");
    }

    @Override
    void buildDisplayScreen() {
        computer.setDisplayScreen("2k 144hz显示器");
        System.out.println("buildDisplayScreen: 2k 60hz显示器");
    }

    @Override
    Computer getComputer() {
        return computer;
    }
}

测试一下

代码语言:javascript
复制
public class Test {
    public static void main(String[] args) {
        MiddleConfigurationComputerBuilder builder = new MiddleConfigurationComputerBuilder();
        // 创建电脑销售中心
        SalesCompany salesCompany = new SalesCompany();
        // 指定具体的电脑建造者去完成 电脑 这个产品
        Computer computer = salesCompany.buildComputer(builder);
        System.out.println("建造出的电脑: " + computer );
    }
}

运行结果

buildCpu: 英特尔酷睿 i7 处理器 buildGraphicsCard: 16g内存 buildDisplayScreen: 2k 60hz显示器 建造出的电脑: Computer{cpu='英特尔酷睿 i7 处理器', graphicsCard='16g内存', displayScreen='2k 144hz显示器'}

其实到这里一个建造者模式的实例就写完了,下面我们结合概念,来深入理解一下建造者模式

三 建造者模式

(一) 概念

建造者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示

  • 也就是说,产品的生成过程或者说组成,是不变的,而每一部分都是可以自行选择的,即其内部表象是可以变化的,这也就是所说的变与不变相分离
  • 此种情况下,用户只需要指定建造的类型就可以得到他们,而具体的过程和细节就不需要知道了

(二) 优缺点

首先,此模式封装性好,构建和表示进行了分离,每一个建造者都是相互独立的,利于解耦和扩展,符合 “开闭原则” 同时客户调用时,不需要知道产品细节

但是也正是因为产品生成过程这个不变的部分,限制了它的使用范围,同时如果产品内部日后发生什么改变,则建造者也得同样修改,维护成本不小

(三) 结构

根据上面的结构图,我们分别说明一下其中的四个角色(除 Client 调用者以外)

  • Product(产品角色):多个组件构成的复杂对象,即上述例子中的电脑
  • Builder(抽象建造者):一个包含创建产品各个子部件的抽象方法的接口/抽象类,一般还包含一个返回结果的方法,如上述中的 ComputerBuilder 类
  • ConcreteBuilder(具体建造者):Builder 的具体实现类,如上述中具体的 低配置电脑建造者 和 中等配置电脑建造者
  • Director(指挥者):调用建造者对象中的部件构造与装配方法,以创建一个复杂对象
  • 指挥者中不含具体产品信息
  • 其隔离了客户与对象的生产过程

(四) 适用场景

  • 顺序会对同一方法的结果产生影响,例如建房子,应当先打地基,再架钢筋水泥
  • 同一个对象可以装配不同的部件或者零件,同时结果不同
  • 产品类有复杂的内部结构,且这些产品对象具有共性

四 结尾

邮箱:ideal_bwh@163.com

如果帮到你的话,那就来关注我吧!

如果您更喜欢微信文章的阅读方式,可以关注我的公众号

如果您更加喜欢PC端的阅读方式,可以访问我的个人博客

域名:www.ideal-20.cn

在这里的我们素不相识,却都在为了自己的梦而努力 ❤ 一个坚持推送原创开发技术文章的公众号:理想二旬不止

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-11-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 理想二旬不止 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一 引言
  • 二 通过例子循序渐进认识建造者模式
    • (一) 最简单直白的方式(不好)
      • (二) 客户直接联系生产技术人员
        • (三) 客户联系销售公司
        • 三 建造者模式
          • (一) 概念
            • (二) 优缺点
              • (三) 结构
                • (四) 适用场景
                • 四 结尾
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档