设计模式之建造者模式

简介

建造者模式在Java中是一个非常常见的设计模式,我们可以在经常看到,比如StringBuilder,HttpRequestBuilder等等。建造者模式是为了解决构造非常复杂的对象而产生的设计模式。它的作用呢是可分步创建复杂对象,并且使用相同的创建代码生成不同的对象,当然了它也保证了创建和使用分离。

实现

首先,举个例子,我现在想要组装一台电脑,电脑有很多部件,应该要怎么实现呢?当然啦,第一反应肯定是创建一个Computer对象,然后把部件填在里面,再new出来就好了。Computer类如下,那么我可以通过构造函数,把所有要的对象都塞进去创建Computer,也可以空的构造函数,然后通过set方法组装Computer。那么为什么不这么做呢?因为如果一个对象只有两三个参数,完全可以这样做的。但是如果有很多参数的话,就会麻烦。另外如果其中的部分参数是可选的,那么就更麻烦一点,可能需要些很多个构造函数来解决此问题。那么建造者模式就是来解决此问题的。

public class Computer {

    private String screen;

    private String cpu;

    private String keyboard;

    private String disk;

    /**
     * 主机
     */
    private String engine;

    private String cache;

    public Computer() {
    }

    public Computer(String screen, String cpu, String keyboard, String disk, String engine,
                    String cache) {
        this.screen = screen;
        this.cpu = cpu;
        this.keyboard = keyboard;
        this.disk = disk;
        this.engine = engine;
        this.cache = cache;
    }

    public String getScreen() {
        return screen;
    }

    public void setScreen(String screen) {
        this.screen = screen;
    }

    public String getCpu() {
        return cpu;
    }

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

    public String getKeyboard() {
        return keyboard;
    }

    public void setKeyboard(String keyboard) {
        this.keyboard = keyboard;
    }

    public String getDisk() {
        return disk;
    }

    public void setDisk(String disk) {
        this.disk = disk;
    }

    public String getEngine() {
        return engine;
    }

    public void setEngine(String engine) {
        this.engine = engine;
    }

    public String getCache() {
        return cache;
    }

    public void setCache(String cache) {
        this.cache = cache;
    }

    @Override
    public String toString() {
        System.out.println("computer is combined by : ---" + getCpu() + "--" + getCache() + "---" + getDisk() + "----" + getEngine() + "----" + getKeyboard() + "----" + getScreen());
        return super.toString();
    }
}

我们先来一个ComputerBuilder

public abstract class ComputerBuilder {

    protected Computer computer = new Computer();

    public abstract ComputerBuilder buyScreen(String screen);

    public abstract ComputerBuilder buyCpu(String cpu);

    public abstract ComputerBuilder buyKeyboard(String keyboard);

    public abstract ComputerBuilder buyDisk(String disk);

    public abstract ComputerBuilder buyEngine(String engine);

    public abstract ComputerBuilder buyCache(String cache);

    public Computer build() {
        return computer;
    }
}

再来个CommonComputerBuilder

public class CommonComputerBuilder extends ComputerBuilder {


    @Override
    public ComputerBuilder buyScreen(String screen) {
        computer.setScreen(screen);
        return this;
    }

    @Override
    public ComputerBuilder buyCpu(String cpu) {
        computer.setCpu(cpu);
        return this;
    }

    @Override
    public ComputerBuilder buyKeyboard(String keyboard) {
        computer.setKeyboard(keyboard);
        return this;
    }

    @Override
    public ComputerBuilder buyDisk(String disk) {
        computer.setDisk(disk);
        return this;
    }

    @Override
    public ComputerBuilder buyEngine(String engine) {
        computer.setEngine(engine);
        return this;
    }

    @Override
    public ComputerBuilder buyCache(String cache) {
        computer.setCache(cache);
        return this;
    }
}

那么现在的我想要组装一台电脑,应该怎么实现呢?

    public static void main(String[] args) {
        //我想组装一台电脑,需要很多配件
        CommonComputerBuilder commonComputerBuilder = new CommonComputerBuilder();
        Computer computer = commonComputerBuilder.buyCache("huawei cache")
                .buyCpu("intel cpu")
                .buyEngine("lenovo engine")
                .buyDisk("sansung disk")
                .buyKeyboard("luoji keyboard")
                .buyScreen("xiaomi screen")
                .build();
        computer.toString();
    }

来看下结果

computer is combined by : ---intel cpu--huawei cache---sansung disk----lenovo engine----luoji keyboard----xiaomi screen

这样的话。我就完全按照自己的想法组装了一台电脑,回头再看介绍,我们解决了构建一个复杂对象,并且可分步创建对象,也完成了使用相同创建代码创建不同对象,完美!另外呢,就是对于扩展性的支持,比如我发现我还需要个鼠标,那么只需要在Computer中添加mouse对象,并在builder中增加buyMouse的方法即可。更完美了!

如果看到这,并且你之前学习过建造者模式,可能会困惑这和我平时学习的建造者模式好像有一些不同!是的,没错,是有所不同,而且开始的时候我也困惑。明明代码中的建造者模式就是和我上面说的一样,可是和理论介绍上的建造者模式不一样。那么现在呢,我有一点小小的理解,分享给大家,还是举组装电脑的例子,我是一个程序员,我想组装一台电脑,因为我本身对电脑各个配件都比较了解,那么我就会希望可以高度定制化一台电脑,以满足我的需求,那么CommonComputerBuilder就非常适合我,我可以选择任何类型的配件,来组装我的电脑。但是呢,假设我是个电脑城卖电脑的老板,顾客来到我这里,说希望组装一台电脑,希望可以满足做设计的需求,或者打游戏的需求,那其实呢我是个有经验的老板,对于这两种需求,我都有流程化的配置,推荐给他们。这时候老板就是director,而特定的builder就是需要的,而我无需每次输入参数。我们来看下代码实现:

public abstract class BossComputerBuilder {

    protected Computer computer = new Computer();

    public abstract BossComputerBuilder buyScreen();

    public abstract BossComputerBuilder buyCpu();

    public abstract BossComputerBuilder buyKeyboard();

    public abstract BossComputerBuilder buyDisk();

    public abstract BossComputerBuilder buyEngine();

    public abstract BossComputerBuilder buyCache();

    public Computer build() {
        return computer;
    }
}

public class DesignerComputerBuilder extends BossComputerBuilder {

    @Override
    public BossComputerBuilder buyScreen() {
        computer.setScreen("designer screen");
        return this;
    }

    @Override
    public BossComputerBuilder buyCpu() {
        computer.setCpu("designer cpu");
        return this;
    }

    @Override
    public BossComputerBuilder buyKeyboard() {
        computer.setKeyboard("designer keyboard");
        return this;
    }

    @Override
    public BossComputerBuilder buyDisk() {
        computer.setDisk("designer disk");
        return this;
    }

    @Override
    public BossComputerBuilder buyEngine() {
        computer.setEngine("designer engine");
        return this;
    }

    @Override
    public BossComputerBuilder buyCache() {
        computer.setCache("designer cache");
        return this;
    }
}

public class GameComputerBuilder extends BossComputerBuilder {

    @Override
    public BossComputerBuilder buyScreen() {
        computer.setScreen("game screen");
        return this;
    }

    @Override
    public BossComputerBuilder buyCpu() {
        computer.setCpu("game cpu");
        return this;
    }

    @Override
    public BossComputerBuilder buyKeyboard() {
        computer.setKeyboard("game keyboard");
        return this;
    }

    @Override
    public BossComputerBuilder buyDisk() {
        computer.setDisk("game disk");
        return this;
    }

    @Override
    public BossComputerBuilder buyEngine() {
        computer.setEngine("game engine");
        return this;
    }

    @Override
    public BossComputerBuilder buyCache() {
        computer.setCache("game cache");
        return this;
    }
}
public class BossDirector {

    private BossComputerBuilder bossComputerBuilder;

    public BossDirector(BossComputerBuilder bossComputerBuilder) {
        this.bossComputerBuilder = bossComputerBuilder;
    }

    public Computer assembleComputer() {
        return bossComputerBuilder.buyCache()
                .buyCpu()
                .buyScreen()
                .buyKeyboard()
                .buyEngine()
                .buyDisk()
                .build();
    }
}

作为电脑城老板,我有两条很固定的业务,那就是游戏电脑和设计师电脑组装,我会先让员工按照固定流程购买指定配件,也就是DesignerComputerBuilder和GameComputerBuilder,然后到我这里BossDirector这里进行组装,我能清晰的看到组装流程和实现(这也是优势之一),并且我这里是不关心组装出来的电脑是什么类型。组装完成了,我们先来看下结果:

computer is combined by : ---game cpu--game cache---game disk----game engine----game keyboard----game screen
computer is combined by : ---designer cpu--designer cache---designer disk----designer engine----designer keyboard----designer screen

所以从这里,我们也能感受到传统建造者模式的另一个优势:特定建造者固定,无法进行修改,减少出现差错的可能性,意思就是我们使用GameComputerBuilder构建的电脑不会出现设计师的配件。当然啦,固定的缺点就是不够灵活。

总结

回归定义,设计模式是一套通用的可复用的解决方案,用来解决在软件设计过程中产生的通用问题。设计模式从来不是一成不变的,永远都需要结合实际情况去做变通。针对需要高灵活性的场景,第一种模式更加适用;而针对变化较少的场景,则第二种模式会更加清晰。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值