《设计模式入门》 5.建造者模式

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

        建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。建造者模式属于对象创建型模式。根据中文翻译的不同,建造者模式又可以称为生成器模式。

        简单来说,假设我们需要装电脑主机,都是电脑但是配置可能不同,有的人光追,有的人想要AMD全家桶。那我们需要的就是创建电脑这个对象,他的构件过程,零件选择,都是不必要知道细节的,全部由我们该出的套餐来进行装机。

建造者模式一般有四个角色:

抽象创建者角色:

给出一个抽象接口,以规范产品对象的各个组成成分的建造。一般而言,此接口独立于应用程序的商业逻辑。模式中直接创建产品对象的是具体创建者角色。具体创建者必须实现这个接口的两种方法:一是建造方法,另一种是结果返回方法。一般来说,产品所包含的零件数目与建造方法的数目相符。换言之,有多少零件,就有多少相应的建造方法。

具体创建者角色:

他们在应用程序中负责创建产品的实例。这个角色要完成的任务包括:
        1、实现抽象创建者所声明的抽象方法,给出一步一步的完成产品创建实例的操作。

        2、在创建完成后,提供产品的实例。

导演者角色:

这个类调用具体创建者角色以创建产品对象。但是导演者并没有产品类的具体知识,真正拥有产品类的具体知识的是具体创建者角色。

产品角色:

产品便是建造中的复杂对象。一般说来,一个系统中会有多于一个的产品类,而且这些产品类并不一定有共同的接口,而完全可以使不相关联的。

=========================================================================

我们模拟一个配电脑的场景:

我们设计有两个电脑套餐,一个AMD全家桶,一个游戏王者,我们根据用户的选择给出相应的配置单。

首先我们根据装机的原材料来抽象一个建造类接口,用于统一标准获取硬件信息。

原材料抽象类:

package BuilderPattern;

import java.math.BigDecimal;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName AbstractComputerBuilder.java
 * @Description 抽象建造类,提供创建产品的共同接口,不同的产品可以有自己的具体实现
 				硬件接口,统一标准获取硬件信息,生成装机配置单
 * @createTime 2022年02月25日 15:18:00
 */
public interface AbstractComputerBuilder {
    /**
     * 硬件种类
     * @return 硬件名
     */
    String name();
    /**
     * 硬件品牌
     * @return 品牌名
     */
    String brand();
    /**
     * 制造商
     * @return 制造商
     */
    String manufacturer();
    /**
     * 型号
     * @return  型号
     */
    String model();
    /**
     * 价格
     * @return  价格
     */
    BigDecimal price();  // 价格
    /**
     * 描述
     * @return  描述
     */
    String desc();
}

然后我们考虑制造的原材料,也就是产品角色类。

我们假设有三类,CPU,GPU和SSD。

CPU:

amd cpu

package BuilderPattern.dao.CPU;

import BuilderPattern.AbstractComputerBuilder;

import java.math.BigDecimal;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName AMD5800X.java
 * @Description AMD5800X
 * @createTime 2022年02月25日 15:45:00
 */
public class AMD5800X implements AbstractComputerBuilder {
    @Override
    public String name() {
        return "CPU";
    }

    @Override
    public String brand() {
        return "AMD";
    }

    @Override
    public String manufacturer() {
        return "MediaTek";
    }

    @Override
    public String model() {
        return "5800X";
    }

    @Override
    public BigDecimal price() {
        return BigDecimal.valueOf(2399);
    }

    @Override
    public String desc() {
        return "八核心十六线程,CPU主频:3.8GHz, 动态加速频率:4.7GHz";
    }
}

Intel cpu

package BuilderPattern.dao.CPU;

import BuilderPattern.AbstractComputerBuilder;

import java.math.BigDecimal;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName Intel12700KF.java
 * @Description AMD5800X
 * @createTime 2022年02月25日 15:43:00
 */
public class Intel12700KF implements AbstractComputerBuilder {
    @Override
    public String name() {
        return "CPU";
    }

    @Override
    public String brand() {
        return "Intel";
    }

    @Override
    public String manufacturer() {
        return "Intel";
    }

    @Override
    public String model() {
        return "12700KF";
    }

    @Override
    public BigDecimal price() {
        return BigDecimal.valueOf(3199);
    }

    @Override
    public String desc() {
        return "十二核心二十线程, CPU主频:3.6GHz, 动态加速频率:4.9GHz";
    }
}

=========================================================================

GPU:

AMD毒药

package BuilderPattern.dao.GPU;

import BuilderPattern.AbstractComputerBuilder;

import java.math.BigDecimal;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName Toxic.java
 * @Description 毒药显卡
 * @createTime 2022年02月25日 15:39:00
 */
public class Toxic implements AbstractComputerBuilder {
    @Override
    public String name() {
        return "Graphic Card";
    }

    @Override
    public String brand() {
        return "AMD";
    }

    @Override
    public String manufacturer() {
        return "Sapphire";
    }

    @Override
    public String model() {
        return "RX6900 XT";
    }

    @Override
    public BigDecimal price() {
        return BigDecimal.valueOf(14999.00);
    }

    @Override
    public String desc() {
        return "核心频率: 2730MHz ,显存频率: 16800MHz, 显存容量: 16GB GDDR6X";
    }
}

七彩虹火神

package BuilderPattern.dao.GPU;

import BuilderPattern.AbstractComputerBuilder;

import java.math.BigDecimal;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName Vulcan.java
 * @Description 火神显卡
 * @createTime 2022年02月25日 15:30:00
 */
public class Vulcan implements AbstractComputerBuilder {
    @Override
    public String name() {
        return "Graphic Card";
    }

    @Override
    public String brand() {
        return "Nvidia";
    }

    @Override
    public String manufacturer() {
        return "Colorful";
    }

    @Override
    public String model() {
        return "GeForce RTX 3090";
    }

    @Override
    public BigDecimal price() {
        return BigDecimal.valueOf(16999.99);
    }

    @Override
    public String desc() {
        return "核心频率: 1395-1860MHz,显存频率: 19500MHz, 显存容量: 24GB GDDR6X";
    }
}

=========================================================================

SSD:

三星

package BuilderPattern.dao.memory;

import BuilderPattern.AbstractComputerBuilder;

import java.math.BigDecimal;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName Samsung980Pro.java
 * @Description Samsung980Pro
 * @createTime 2022年02月25日 15:51:00
 */
public class Vnand implements AbstractComputerBuilder {
    @Override
    public String name() {
        return "Memory";
    }

    @Override
    public String brand() {
        return "Samsung";
    }

    @Override
    public String manufacturer() {
        return "Samsung";
    }

    @Override
    public String model() {
        return "980Pro";
    }

    @Override
    public BigDecimal price() {
        return BigDecimal.valueOf(1399.00);
    }

    @Override
    public String desc() {
        return "1TB SSD PCIE4.0 M.2";
    }
}

SN850

package BuilderPattern.dao.memory;

import BuilderPattern.AbstractComputerBuilder;

import java.math.BigDecimal;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName SN850.java
 * @Description SN850
 * @createTime 2022年02月25日 15:55:00
 */
public class WdBlack implements AbstractComputerBuilder {
    @Override
    public String name() {
        return "Memory";
    }

    @Override
    public String brand() {
        return "Western Digital";
    }

    @Override
    public String manufacturer() {
        return "SanDisk";
    }

    @Override
    public String model() {
        return "SN850";
    }

    @Override
    public BigDecimal price() {
        return BigDecimal.valueOf(1499.00);
    }

    @Override
    public String desc() {
        return "1T SSD PCIE4.0 M.2";
    }
}

=========================================================================

然后根据以上的原材料,组装成不同的配置单

这时候我们就使用一个抽象创建者角色来实现创建配置单:

package BuilderPattern;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName Builder.java
 * @Description 抽象创建者角色
 * @createTime 2022年02月25日 16:48:00
 */
public interface ListBuilder {
    //添加CPU信息
    ListBuilder appendCpu(AbstractComputerBuilder abs);
    //添加GPU信息
    ListBuilder appendGpu(AbstractComputerBuilder abs);
    //添加SSD信息
    ListBuilder appendSSD(AbstractComputerBuilder abs);
    //获取实例
    String getDetail();
}

=========================================================================

使用具体创建者角色来实现抽象创建者,并返回配置单。

package BuilderPattern;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName ComputerList.java
 * @Description 具体创建者角色
 * @createTime 2022年02月25日 16:51:00
 */
public class ComputerList implements ListBuilder{
    private List<AbstractComputerBuilder> computerList = new ArrayList<>();
    private BigDecimal price = BigDecimal.ZERO;
    private String level;

    public ComputerList() {
    }

    public ComputerList(String level) {
        this.level = level;
    }

    @Override
    public ListBuilder appendCpu(AbstractComputerBuilder abs) {
        computerList.add(abs);
        price = price.add(abs.price());
        return this;
    }

    @Override
    public ListBuilder appendGpu(AbstractComputerBuilder abs) {
        computerList.add(abs);
        price = price.add(abs.price());
        return this;
    }

    @Override
    public ListBuilder appendSSD(AbstractComputerBuilder abs) {
        computerList.add(abs);
        price = price.add(abs.price());
        return this;
    }

    @Override
    public String getDetail() {
        StringBuilder detail = new StringBuilder("\r\n============================================\r\n" +
                "配置清单" + "\r\n" +
                "电脑等级:" + level + "\r\n" +
                "总价:" + price.setScale(2, RoundingMode.HALF_UP) + " 元\r\n" +
                "配件清单:\r\n");

        for (AbstractComputerBuilder abs:computerList) {
            detail. append(abs.name()).append(": ").
                    append(abs.brand()).append(", ").
                    append(abs.model()).append(", ").
                    append(abs.manufacturer()).append(", ").
                    append(abs.desc()).append(", ").
                    append(abs.price()).append("\n");
        }
        return detail.toString();
    }
}

=========================================================================

导演者角色创建产品对象。  

package BuilderPattern;

import BuilderPattern.dao.CPU.AMD5800X;
import BuilderPattern.dao.CPU.Intel12700KF;
import BuilderPattern.dao.GPU.Toxic;
import BuilderPattern.dao.GPU.Vulcan;
import BuilderPattern.dao.memory.Vnand;
import BuilderPattern.dao.memory.WdBlack;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName Builder.java
 * @Description 导演者角色
 * @createTime 2022年02月25日 16:57:00
 */
public class Actor {
    public ComputerList levelOne(String level){
        return (ComputerList) new ComputerList(level).appendCpu(new AMD5800X()).appendGpu(new Toxic()).appendSSD(new WdBlack());
    }

    public ComputerList levelTwo(String level){
        return (ComputerList) new ComputerList(level).appendCpu(new Intel12700KF()).appendGpu(new Vulcan()).appendSSD(new Vnand());
    }
}

这样就实现了使用建造者模式创造一个配置单。

=========================================================================

测试一下:

        用户只用告诉我们他想要游戏王者还是AMD全家桶,我们就可以给他对应的配置单,用户不需要了解内部具体的创建过程。

package BuilderPattern;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName ComputerListTest.java
 * @Description 游戏配置单测试类
 * @createTime 2022年02月25日 16:20:00
 */
public class ComputerListTest {
    public static void main(String[] args) {
        String level = "游戏王者";
        getComputerList(level);

    }

    public static void getComputerList(String level){
        /*
         * 创建导演类和的建造者
         */
        Actor actor = new Actor();

        /*
         * 利用导演类来获得单子
         */
        if ("AMD全家桶".equals(level)) {
            System.out.println(actor.levelOne(level).getDetail());
        }else if ("游戏王者".equals(level)){
            System.out.println(actor.levelTwo(level).getDetail());
        }else {
            System.out.println("选择错误");
        }
    }
}

 

=========================================================================

优点:

  1. 在建造者模式中, 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
  2. 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。
  3. 可以更加精细地控制产品的创建过程 。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
  4. 增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”。

缺点:

  1. 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。

  2. 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PigeonEssence

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值