设计模式之建造者模式

建造者模式

需求: 定义一个电脑类,并实例化该电脑类对象,并为该对象的属性赋值

1、平时创建对象并赋值的方式

平时,我们在实例化对象之后必须为该对象的每一个属性赋值,这样对我们来说太麻烦了,而且还违反了迪米特法则。

我们的例子来说,这就相当于我们我们去买电脑,商家把所有配件给我们,叫我们自己组装

class Computer {
    private String cpu;
    private String gpu;
    private String memery;
    private String hd;

   //....省略get,set方法以及toString方法
}
//以上为客户端,以下为服务端,我们角色为客户(客户端可以随意修改,服务端我们不能操作)
//====================================================================
public class AppTest {

    public static void main(String[] args) {
        Computer computer = new Computer();
        computer.setCpu("");
        computer.setGpu("");
        computer.setHd("");
        computer.setMemery("");
    }

这样做的缺点是

  1. 客户端程序员在实例化产品对象之后,必须为该对象的每一个属性赋值,这样对于客户端程序员来讲,太麻烦了。
  2. 违背了迪米特法则

建造者模式与工厂模式的区别:
工厂模式:是直接实例化出一个类的对象即可
建造者模式:实例化类的对象之后,还要给类的属性赋值

2、创建一个专门用于创建电脑的建造类

针对上面的问题,我们专门创建一个ComputerBuilder类,专门用于创建对象

class Computer {
    private String cpu;
    private String gpu;
    private String memery;
    private String hd;
    //省略get,set,toString方法
}

//低配电脑
class LowComputerBuilder {
    private Computer computer = new Computer();
    public Computer build(){
        computer.setCpu("");
        computer.setGpu("");
        computer.setHd("");
        computer.setMemery("");
        return computer;
    }
}

//中配电脑
class MiddleComputerBuilder {
    private Computer computer = new Computer();
    public Computer build(){
        computer.setCpu("");
        computer.setGpu("");
        computer.setHd("");
        computer.setMemery("");
        return computer;
    }
}

//高配电脑
class HeightComputerBuilder {
    private Computer computer = new Computer();
    public Computer build(){
        computer.setCpu("");
        computer.setGpu("");
        computer.setHd("");
        computer.setMemery("");
        return computer;
    }
}

//====================================================================
public class AppTest {
    public static void main(String[] args) {
        //购买低配电脑
        LowComputerBuilder c1 = new LowComputerBuilder();
        Computer build = c1.build();

        //购买中配电脑
        MiddleComputerBuilder c2 = new MiddleComputerBuilder();
        Computer build1 = c2.build();

        //购买高配电脑
        HeightComputerBuilder c3 = new HeightComputerBuilder();
        Computer build2 = c3.build();
    }
}

这样设计仍然不属于建造者模式。
优点:

  1. 可以根据不同的需求,使用不同的建造着来进行生产

缺点:

  1. 我们发现不同的建造者中的代码,在重复,既然代码中出现了重复的代码,那就有了“坏味道”
  2. 建造的过程不稳定,如果在建造者在建造的过程中,如果漏掉了某一部(比如创建的过程中中cup,gpu,hq都装了,但是没有装memary),编译器也不会报错。(举个例子来说,就类似于KFC的某一家分店,在制作汉堡包的过程中突然少了某一个步骤,出来的汉堡包的味道就变了,因为没有标准)

3、创建规范接口,规范创建的类

针对2中产生的问题,修改代码如下:
创建一个建造者接口,吧制作的具体流程稳定下来,我们让建造者类去实现建造者接口,接口中的方法步骤类都必须进行实现,少实现一个抽象方法就会报错。

class Computer {
    private String cpu;
    private String gpu;
    private String memery;
    private String hd;
    // .....   此处省略get,set方法
}

interface ComputerBuilder {
    void setCpu();
    void setGpu();
    void setHd();
    void setMemary();
    Computer build();
}
//低配
class LowComputer implements ComputerBuilder{
    private Computer c = new Computer();

    @Override
    public void setCpu() {
        c.setCpu("1");
    }

    @Override
    public void setGpu() {
        c.setGpu("2");
    }

    @Override
    public void setHd() {
        c.setHd("3");
    }

    @Override
    public void setMemary() {
        c.setMemery("4");
    }

    @Override
    public Computer build() {
        return c;
    }
}
//中配
class MiddleComputer implements ComputerBuilder{
    private Computer c = new Computer();

    @Override
    public void setCpu() {
        c.setCpu("3");
    }

    @Override
    public void setGpu() {
        c.setGpu("3");
    }

    @Override
    public void setHd() {
        c.setHd("3");
    }

    @Override
    public void setMemary() {
        c.setMemery("3");
    }

    @Override
    public Computer build() {
        return c;
    }
}
//高配
class HeightComputer implements ComputerBuilder{
    private Computer c = new Computer();

    @Override
    public void setCpu() {
        c.setCpu("4");
    }

    @Override
    public void setGpu() {
        c.setGpu("4");
    }

    @Override
    public void setHd() {
        c.setHd("4");
    }

    @Override
    public void setMemary() {
        c.setMemery("4");
    }

    @Override
    public Computer build() {
        return c;
    }
}

//====================================================================
public class AppTest {

    public static void main(String[] args) {
        LowComputer c1 = new LowComputer();
        MiddleComputer c2 = new MiddleComputer();
        HeightComputer c3 =  new HeightComputer();
        //低配电脑
        c1.setCpu();
        c1.setGpu();
        c1.setHd();
        c1.setMemary();
        Computer build = c1.build();

        //中配电脑
        c2.setCpu();
        c2.setGpu();
        c2.setHd();
        c2.setMemary();
        Computer build1 = c2.build();

        //高配电脑
        c3.setCpu();
        c3.setGpu();
        c3.setHd();
        c3.setMemary();
        Computer build2 = c3.build();

        System.out.println(build);
        System.out.println(build1);
        System.out.println(build2);
    }
}

这个还不是构造者模式,
优点:

  1. 建造类中建造过程使稳定的,不会漏掉某一步,这样客户端想要扩展建造者时,也不会漏掉某一步。

缺点:

  1. 代码任然重复
  2. 现在又变成了客户端自己来进行配置电脑,又违反了迪米特法则(着相当于你去赛格配置电脑,虽然不用你亲自组装电脑,但是你必须指挥那个组装电脑的人,该装什么该装什么),如果你在指挥的过程中如果漏了哪一步,依旧会使该电脑缺少一些部件或者功能。

4、创建一个指挥者,用于创建电脑(这就是建造者模式)

针对上面的的问题,我们创建一个指挥者Director,用于指挥商品的创建

class Computer {
    private String cpu;
    private String gpu;
    private String memery;
    private String hd;
    // .... 此处省略get set方法
}

interface ComputerBuilder {
    void setCpu();
    void setGpu();
    void setHd();
    void setMemary();
    Computer build();
}
//低配
class LowComputer implements ComputerBuilder{
    private Computer c = new Computer();

    @Override
    public void setCpu() {
        c.setCpu("1");
    }

    @Override
    public void setGpu() {
        c.setGpu("2");
    }

    @Override
    public void setHd() {
        c.setHd("3");
    }

    @Override
    public void setMemary() {
        c.setMemery("4");
    }

    @Override
    public Computer build() {
        return c;
    }
}
//中配
class MiddleComputer implements ComputerBuilder{
    private Computer c = new Computer();

    @Override
    public void setCpu() {
        c.setCpu("3");
    }

    @Override
    public void setGpu() {
        c.setGpu("3");
    }

    @Override
    public void setHd() {
        c.setHd("3");
    }

    @Override
    public void setMemary() {
        c.setMemery("3");
    }

    @Override
    public Computer build() {
        return c;
    }
}
//高配
class HeightComputer implements ComputerBuilder{
    private Computer c = new Computer();

    @Override
    public void setCpu() {
        c.setCpu("4");
    }

    @Override
    public void setGpu() {
        c.setGpu("4");
    }

    @Override
    public void setHd() {
        c.setHd("4");
    }

    @Override
    public void setMemary() {
        c.setMemery("4");
    }

    @Override
    public Computer build() {
        return c;
    }
}

//指挥者
class Director {
    public Computer build(ComputerBuilder builder){
        builder.setCpu();
        builder.setGpu();
        builder.setMemary();
        builder.setHd();
        return builder.build();
    }
}

//====================================================================
public class AppTest {

    public static void main(String[] args) {
        Director director = new Director();

        LowComputer c1 = new LowComputer();
        MiddleComputer c2 = new MiddleComputer();
        HeightComputer c3 =  new HeightComputer();
        //低配电脑
        Computer build = director.build(c1);
        //中配电脑
        Computer build1 = director.build(c2);
        //高配电脑
        Computer build2 = director.build(c3);

        System.out.println(build);
        System.out.println(build1);
        System.out.println(build2);
    }
}

这就是建造者模式
优点:

  1. 创建过程是稳定不变的(因为有ComputerBuilder接口来稳定过程)
  2. 创建过程只写了一次,没有重复的代码(由Director指挥完成)

以上内容为课后总结,如有侵权,请告知本人!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值