【设计模式】创建型-建造者模式

干了很多年的程序员了,我今天终于要实现人生梦想的第一步,a dream car 保时捷卡宴。我兴冲冲的跑到保时捷4S店,来到这里,不禁为4S店的豪华装修感到震撼,也为这里的每一辆车感到惊艳~这时售车小姐姐拿起车辆配置单,我就刷刷刷的选了好几种配置的车型,最终确定了某个配置。处于好奇就问了妹子造车的过程:

public static class CayenneZhuMengBan {
    public void engine() {
        System.out.println("组装发动机:3.0T V6");
    }

    public void cruise() {
        System.out.println("刷入巡航系统:定速巡航");
    }

    public void sound() {
        System.out.println("组装音响:BOSS");
    }

    public void build() {
        System.out.println("建造卡宴逐梦版");
    }
}

public static class CayenneCoupeGT {
    public void engine() {
        System.out.println("组装发动机:4.0T V8");
    }

    public void cruise() {
        System.out.println("刷入巡航系统:全速自适应巡航");
    }

    public void sound() {
        System.out.println("组装音响:柏林之声");
    }

    public void build() {
        System.out.println("建造卡宴CoupeGT版");
    }

}

客户端代码:

public static void main(String[] args) {
    CayenneZhuMengBan zhuMengBan = new CayenneZhuMengBan();
    zhuMengBan.engine();
    zhuMengBan.sound();
    zhuMengBan.cruise();
    zhuMengBan.build();

    CayenneCoupeGT coupeGT = new CayenneCoupeGT();
    coupeGT.engine();
    coupeGT.sound();
    coupeGT.cruise();
    coupeGT.build();
}

身为程序员的我一眼发现问题所在。卡宴车型那么多,而且还有选配。

问题一:如果为每一种配置或配置组合都写一个类,那么不就是类爆炸了吗?不符合开闭原则。那我用工厂模式不就行了吗?不太准确,工厂模式侧重生产产品,保时捷工厂只生产保时捷汽车(车型,如卡宴,paramecia等),不应负责具体装车细节。这里提一下,如果工厂模式既生产车型,又负责组装车,那么他就不符合设计模式的“单一原则”。单一原则强调,每个类,接口,功能模块等都应该只有一种职责。过多的职责会带来,代码臃肿,责任不明确,解耦困难。就像我们工作一样,让你即写代码又去做产品经理,项目经理,能干好不??

问题二:造车的过程都是有顺序,肯定需要先安装发动机(假如),才能再安装音响呀,巡航系统呀,如果负责装配零件的工人搞错了顺序,那不就完蛋了?!

问题三:应该给卡宴汽车一个抽象,不应该具体化为逐梦版,CoupeGT版等,后期想新增配置车型会非常困难,不易于维护,其实还是不符合开闭原则

我把造成的车问题反馈给了保时捷,保时捷设计师傅说“你的方案真不错,我们优化一下”

建立抽象建造者类:

public interface Builder {
    void engine();
    void sound();
    void cruise();
    CayenneCar build();
}

建立保时捷卡宴车类(产品):

public class CayenneCar {
    private String model;
    private String engine;
    private String sound;
    private String cruise;

    public CayenneCar(String model) {
        this.model = model;
    }

    @Override
    public String toString() {
        return "CayenneCar{" +
                "model='" + model + '\'' +
                ", engine='" + engine + '\'' +
                ", sound='" + sound + '\'' +
                ", cruise='" + cruise + '\'' +
                '}';
    }
}

建立抽象建造者的实现类,逐梦版与CoupeGT版类:

public class ZhuMengBanBuilder implements Builder {
    private CayenneCar cayenneCar = new CayenneCar("卡宴逐梦版");

    public void engine() {
        System.out.println("组装发动机:3.0T V6");
        cayenneCar.engine = "3.0T V6";
    }

    public void cruise() {
        System.out.println("刷入巡航系统:定速巡航");
        cayenneCar.cruise = "定速巡航";
    }

    public void sound() {
        System.out.println("组装音响:BOSS");
        cayenneCar.sound = "BOSS";
    }

    public CayenneCar build() {
        return cayenneCar;
    }
}

public class CoupeGTBuilder implements Builder {
    private CayenneCar cayenneCar = new CayenneCar("卡宴逐梦版");

    public void engine() {
        System.out.println("组装发动机:4.0T V8");
        cayenneCar.engine = "4.0T V8";
    }

    public void cruise() {
        System.out.println("刷入巡航系统:全速自适应巡航");
        cayenneCar.cruise = "全速自适应巡航";
    }

    public void sound() {
        System.out.println("组装音响:柏林之声");
        cayenneCar.sound = "柏林之声";
    }

    public CayenneCar build() {
        return cayenneCar;
    }
}

建立指挥者类(保时捷装配工):

public class PorscheAssembler{

    public void assemble(Builder builder) {
        builder.engine();
        builder.sound();
        builder.cruise();
    }
}

客户端代码:

public static void main(String[] args) {

    Builder zhuMengBanBuilder = new ZhuMengBanBuilder();
    Builder coupeGTBuilder = new CoupeGTBuilder();

    PorscheAssembler assembler = new PorscheAssembler();

    assembler.assemble(zhuMengBanBuilder);
    CayenneCar zhuMengCar = zhuMengBanBuilder.build();
    System.out.println(zhuMengCar);

    assembler.assemble(coupeGTBuilder);
    CayenneCar coupeGT = coupeGTBuilder.build();
    System.out.println(coupeGT);
}

总结:

经过建造者模式装配的卡宴汽车,仅需根据不同的配置建立不同的Builder类,就可以构造出不同的卡宴车型,符合开闭原则。它隐藏了建造产品的复杂细节,使产品构造与产品本身解耦。由于建造者只负责建造,所以符合单一原则。这里再提一个,里氏替换原则,这个原则是开闭原则的一个实现,即子类一定可以替换父类,其实就是说的面向对象的继承。在我们保时捷的代码中,CoupeGTBuilder类一定可以替换成Builder类,即CoupeGTBuilder coupeGTBuilder = new CoupeGTBuilder(); 

我们的代码中其实也有些地方需要改进,产品类CayenneCar类我们应该把它改成接口,不应该限制为专有车型卡宴,因为无论哪种车型,装配的动作基本上都是一致的,就像每个车型都有装配发动机,装配轮胎等等,即使有不同车型有不同的地方,我们可以在里面用桥接模式或者其他复合模式(各种模式的组合)。如果产品的构造不复杂,且无顺序要求,那就没有必要用指挥者类了,可以把构造的过程直接写在Builder类的build方法中。还有一点,Builder类接口中定义的方法,也可以带上参数,客户端负责动态传入。

最后给出GOF的官方定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

demo地址:GitCode - 全球开发者的开源社区,开源代码托管平台

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Diros2025

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

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

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

打赏作者

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

抵扣说明:

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

余额充值