建造者模式

视频链接:https://www.bilibili.com/video/BV1eK4y1C7zi/

 

建造者模式

建造者模式也是属于创建型模型,是23种GOF之一。

定义:将一个复杂对象的构建和它的表示分离,使同样的构建构成可以创建不同的表示。

建造者模式适用于一个复杂的对象的建造,而且在建造的过程中,客户端不必知道产品内部组成的细节。

这里的表示,我们用一个具体的例子来说明

建造者模式中的角色

建造者(Builder)模式由产品、抽象建造者、具体建造者、指挥者等 4 个要素构成,

建造者(Builder):为创建一个产品对象的各个部件指定抽象接口。

具体建造者(ConcreteBuilder):实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,并提供一个检索产品的接口。

指挥者(Director):指挥并构造一个使用Builder接口的对象。

产品(Product):表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类,包括将这些部件装配成最终产品的接口。

 

我们这里有一需求

需求: 定义一个电脑类,电脑有很多属性,并且实例化电脑类的对象,以及给该对象赋值。

我们先不用构造者模式来实现一下

public class Computer{
    private String cpu;
    private String gpu;
    private String memery;
    private String hd;
    /*
     * ................
     * */

    public String getCpu() {
        return cpu;
    }

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

    public String getGpu() {
        return gpu;
    }

    public void setGpu(String gpu) {
        this.gpu = gpu;
    }

    public String getMemery() {
        return memery;
    }

    public void setMemery(String memery) {
        this.memery = memery;
    }

    public String getHd() {
        return hd;
    }

    public void setHd(String hd) {
        this.hd = hd;
    }

    @Override
    public String toString() {
        return "Computer{" +
                "cpu='" + cpu + '\'' +
                ", gpu='" + gpu + '\'' +
                ", memery='" + memery + '\'' +
                ", hd='" + hd + '\'' +
                '}';
    }
}

// 测试
public class BuilderTest {
    public static void main(String[] args) {
        Computer computer = new Computer();
        computer.setCpu("i5 9300H");
        computer.setGpu("gtx1650");
        computer.setMemery("16G");
        computer.setHd("256ssd + 1T机械");

        System.out.println(computer);
    }
}

/**
 * 我们先不用建造者模式,看看会有什么问题??
 * 1. 客户端程序,在实例化好产品之后,必须为该对象的每一个属性赋值,这样对客户端程序员来说,太复杂了,需要了解compter类的细节
 * 2. 违反了迪米特原则(最少知道原则)
 * 3. 客户端程序new出来computer对象不能立刻使用,需要设置很多属性
 *
 * 相当于你去买电脑,商家不是把电脑成品直接给你,而是给你一堆零件,让你自己组装
 *
 * 建造者模式与工厂模式的区别:
 * 工厂模式,都是直接实例化出一个类的对象即可。
 * 建造者模式,是在实例化出类的对象之后,还要给该对象每一个属性赋值!
 */

结果

 

 

我们改进一下代码

/**
 * 电脑建造者类,建造者类,必须关联电脑产品
 * 关联:一个类的对象,作为另一个类的对象成员
 */
public class ComputerBuilder {
    private Computer computer = new Computer();

    public Computer build(){
        computer.setCpu("i7 8750HK");
        computer.setGpu("RTX2080");
        computer.setMemery("32G");
        computer.setHd("512ssd + 2T机械");
        return computer;
    }
}

//如果不同客户有不同需求呢?

public class V1Test {
    public static void main(String[] args) {
        // 创建一个建造者
        ComputerBuilder computerBuilder = new ComputerBuilder();
        // 玩游戏
        Computer computer = computerBuilder.build();
        System.out.println(computer);
        // 开发
        Computer computer2 = computerBuilder.build();
        System.out.println(computer2);
        // 办公
        Computer computer3 = computerBuilder.build();
        System.out.println(computer3);
    }
}

/**
 * 目前这种写法还不是建造者模式,目前的优点:
 * 1. 客户端程序员需要一个产品时,直接向建造者要即可,建造者封装了电脑建造的复杂过程
 *
 * 目前缺点:
 * 1. 封装的太过了,无论客户是什么需求,都是采用最高的配置
 * 这相当于你去买电脑,不管你是买来干嘛的,商家都会给你配置最贵的电脑!
 *
 */

结果

 

 这也不符合常理,我们再改进一下。

创建三个不同的建造者

/**
 * 电脑建造者类,建造者类,必须关联电脑产品
 * 关联:一个类的对象,作为另一个类的对象
 */
public class AdvancedComputerBuilder {
    private Computer computer = new Computer();

    public Computer build(){
        computer.setCpu("i7 8750HK");

        computer.setMemery("32G");
        computer.setHd("512ssd + 2T机械");
        return computer;
    }
}

public class MiddleComputerBuilder {
    private Computer computer = new Computer();

    public Computer build(){
        computer.setCpu("i7 7700hq");
        computer.setGpu("gtx1060");
        computer.setMemery("16G");
        computer.setHd("256ssd + 1T机械");
        return computer;
    }
}

public class LowComputerBuilder {
    private Computer computer = new Computer();

    public Computer build(){
        computer.setCpu("i5 7500u");
        computer.setGpu("gtx940mx");
        computer.setMemery("8G");
        computer.setHd("1T机械");
        return computer;
    }
}

public class V2Test {
    public static void main(String[] args) {
        // 玩游戏
        AdvancedComputerBuilder advancedComputerBuilder = new AdvancedComputerBuilder();
        Computer computer = advancedComputerBuilder.build();
        System.out.println(computer);
        // 开发
        MiddleComputerBuilder middleComputerBuilder = new MiddleComputerBuilder();
        Computer computer2 = middleComputerBuilder.build();
        System.out.println(computer2);
        // 办公
        LowComputerBuilder lowComputerBuilder = new LowComputerBuilder();
        Computer computer3 = lowComputerBuilder.build();
        System.out.println(computer3);
    }
}

/**
 *针对不同的需求,我们需要创建不同的建造者,来分别生产不同配置的产品
 *
 * 这仍不是建造者模式
 * 优点:
 * 1. 可以根据客户端的不同需求,使用不同的建造者生产产品
 *
 * 缺点:
 * 1. 我们发现多个建造者中的代码在重复!出现了重复代码
 * 2. 建造过程不稳定,如何在某个建造者创建产品的过程中,漏掉了某一步,编译器也不会提示。没有标准
 */

还不行,再改进一下。

我们将建造电脑的过程抽象出来定义一个接口,以后不管什么配置的电脑,都是按照这个步骤走,相当于定义了一套规范,将建造过程稳定下来。

public interface ComputerBuilder {
    void setCpu();
    void setGpu();
    void setMemery();
    void setHd();
    Computer build();
}


public class AdvancedComputerBuilder implements ComputerBuilder{
    private Computer computer = new Computer();

    @Override
    public void setCpu() {
        computer.setCpu("i7 8750HK");
    }

    @Override
    public void setGpu() {
        computer.setGpu("RTX2080");
    }

    @Override
    public void setMemery() {
        computer.setMemery("32G");
    }

    @Override
    public void setHd() {
        computer.setHd("512ssd + 2T机械");
    }

    public Computer build(){
        return computer;
    }
}


public class MiddleComputerBuilder implements ComputerBuilder{
    private Computer computer = new Computer();

    @Override
    public void setCpu() {
        computer.setCpu("i7 7700hq");
    }

    @Override
    public void setGpu() {
        computer.setGpu("gtx1060");
    }

    @Override
    public void setMemery() {
        computer.setMemery("16G");
    }

    @Override
    public void setHd() {
        computer.setHd("256ssd + 1T机械");
    }

    public Computer build(){
        return computer;
    }
}


public class LowComputerBuilder implements ComputerBuilder{
    private Computer computer = new Computer();

    @Override
    public void setCpu() {
        computer.setCpu("i5 7500u");
    }

    @Override
    public void setGpu() {
        computer.setGpu("gtx940mx");
    }

    @Override
    public void setMemery() {
        computer.setMemery("8G");
    }

    @Override
    public void setHd() {
        computer.setHd("1T机械");
    }

    public Computer build(){
        return computer;
    }
}
public class V3Test {
    public static void main(String[] args) {
        // 玩游戏
        AdvancedComputerBuilder advancedComputerBuilder = new AdvancedComputerBuilder();
        advancedComputerBuilder.setCpu();
        advancedComputerBuilder.setGpu();
        advancedComputerBuilder.setMemery();
        advancedComputerBuilder.setHd();
        Computer computer = advancedComputerBuilder.build();
        System.out.println(computer);
        // 开发
        MiddleComputerBuilder middleComputerBuilder = new MiddleComputerBuilder();
        middleComputerBuilder.setCpu();
        middleComputerBuilder.setGpu();
        middleComputerBuilder.setMemery();
        middleComputerBuilder.setHd();
        Computer computer2 = middleComputerBuilder.build();
        System.out.println(computer2);
        // 办公
        LowComputerBuilder lowComputerBuilder = new LowComputerBuilder();
        lowComputerBuilder.setCpu();
        lowComputerBuilder.setGpu();
        lowComputerBuilder.setMemery();
        lowComputerBuilder.setHd();
        Computer computer3 = lowComputerBuilder.build();
        System.out.println(computer3);
    }
}
/**
 *创建一个建造者的抽象接口,把制作产品的具体步骤稳定下来。
 * 我们让建造者类,去实现建造者接口,接口中的方法步骤,类必须都要实现,少一个则会报错
 *
 * 优点:
 * 建造者类中的建造过程是稳定的。不会漏掉某一步!!这样客户端想扩展建造者时,也不会漏掉某一步
 *
 * 缺点:
 * 1. 代码依然重复
 * 2. 现在又变成了客户端自己配电脑,又违反了迪米特法则。
 * (相当于你去买电脑,虽然不用你亲自组装电脑,但是必须“指挥”那个装机的人,该装。。该装什么。。)
 */
又变成了客户端自己配电脑,又违反了迪米特法则!!!
下面是我们真正的建造者模式了
public class Director {
    public Computer build(ComputerBuilder cb){
        cb.setCpu();
        cb.setGpu();
        cb.setMemery();
        cb.setHd();
        return cb.build();
    }
}


public class V4Test {
    public static void main(String[] args) {

        AdvancedComputerBuilder advancedComputerBuilder = new AdvancedComputerBuilder();
        MiddleComputerBuilder middleComputerBuilder = new MiddleComputerBuilder();
        LowComputerBuilder lowComputerBuilder = new LowComputerBuilder();
        Director director = new Director();

        // 玩游戏
        Computer computer = director.build(advancedComputerBuilder);
        System.out.println(computer);
        // 开发

        Computer computer2 = director.build(middleComputerBuilder);
        System.out.println(computer2);
        // 办公

        Computer computer3 = director.build(lowComputerBuilder);
        System.out.println(computer3);
    }
}

/**
 *这就是建造者模式
 * 优点:
 *  1. 创建对象的过程是稳定不变的
 *  2. 创建对象的过程只写了一次,没有重复代码(指挥者完成)
 *  3. 当需要扩展指挥者的时候,不用修改之前的代码,符合开闭原则
 *
 *
 *  建造者模式与工厂模式的区别
 *  工厂模式只需要一个简单的new,new出产品即可。
 *  建造者更注重,在new出产品之后的,为产品赋值的过程!
 */

这就是我们的建造者模式,显然它是符合开闭原则的,假如一个客户需要中高配的电脑,我们只需要新建一个中高配电脑的builder,去实现ComputerBuilder接口,再传入Directer类build就行了,不需要改变之前的代码。

而一开始说到的表示,就是这这几个不同配置电脑的建造者,LowComputerBuilder,MiddleComputerBuilder和AdvancedComputerBuilder

最后来说下建造者模式与工长模式的区别:

1.工厂模式只需要一个简单的new,new出产品即可。
2.建造者更注重,在new出产品之后的,为产品赋值的过程
posted @ 2020-03-28 21:43  涤生-  阅读(192)  评论(0编辑  收藏  举报