理解设计模式——创建型模式(3)生成器模式

生成器模式

生成器模式结构

  1. 抽象产品类 -->(可以有,但没必要)
  2. 具体产品类
  3. 抽象生成器 -->(规定了生产产品的必要步骤)
  4. 具体生成器 -->(包含生产一个产品必须的所有具体步骤和细节 )
  5. 主管类 -->(“操控”生成器生产具体产品)

生成器模式特点

  1. 想要创建的一系列的对象,这些对象首先初始化比较复杂和繁琐其次制造过程很相似仅仅有细节上的差异的时候,可以考虑使用生成器模式(下面会有举例说明)。
  2. 生成器模式中的“抽象/具体生成器”,很容易类比为工厂模式中的“抽象/具体工厂”。但是他们的区别是显著的:“具体工厂”会直接产出具体产品(对象),而“具体生成器”并不负责生产具体产品(对象)的过程。具体可以看下面的代码和总结。
  3. 生成器模式的目的不是生产同一系列的产品。由不同生成器生成的最终具体产品不一定要属于同一接口或抽象类(因此抽象产品类不是必须的)。

讲个故事

  话接上回,主要讲到逆丰快递公司使用抽象工厂造飞机、造汽车。所谓造化弄人天妒英才,老板这次玩脱了。由于成本太高而收益有限,逆丰快递不得不砍掉飞机业务,从此专注造汽车和陆上运输。所以今天我只能说说造汽车的事啦(有点遗憾,因为造飞机我也会)。
  说到造汽车,首先,要确定汽车有哪些组成部分。车轮、方向盘、油门这些肯定必须的,还有一些细节视车的种类而定,比如有没有离合器?柴油发动机还是汽油发动机?有没有车载导航?有没有车顶(比如我家的帕加尼风之子和保时捷911就没有车顶)等等,可以看到造一辆车要素还是比较多的,具体步骤当然也会比较繁琐。
  不多说开始造车。按照先前的套路,应该是这样的一个步骤:
在这里插入图片描述
有问题吗?大问题倒也没有,也就代码冗余丑陋点,构造函数庞大繁琐点,调用麻烦点,无用参数过多了点。。。
  有更好的解决方案吗?当然有,比如生成器模式如下,源码附在文尾。

抽象和具体产品类:

/**
 * 抽象产品类
 * 可以有,但没必要。因为生成器模式并非只能生产同一系列的产品。
 */
public abstract class Car {
    public String carType;
    abstract void info();
}

/**
 * 具体产品1:保时捷(其实就是一个POJO)
 */
public class Posche extends Car {
    // 轮胎个数
    private Integer wheel;
    // 方向盘个数
    private Integer steering;
    // 油门个数
    private Integer acclerator;
    // 离合器个数
    private Integer clutch;
    // 柴油发动机
    private String dieselEngine;
    // 汽油发动机
    private String gasolineEngine;
    // 车载导航
    private String navigator;
    // 车顶棚
    private String top;

	// (篇幅原因这里省略各属性的setter/getter方法)
	// ......

    @Override
    public void info() {
        String desc = "这是一辆" + carType + ":\n" +
                wheel + "个车轮\n" +
                steering + "个方向盘\n" +
                acclerator + "个油门\n" +
                clutch + "个离合器\n" +
                "柴油发动机:" + dieselEngine + "\n" +
                "汽油发动机:" + gasolineEngine + "\n" +
                "车载导航:" + navigator + "\n" +
                "车顶棚:" + top + "\n";
        System.out.println(desc);
    }
}

/**
 * 具体产品2:五菱宏光(其实就是一个POJO)
 */
public class Wuling extends Car {
    // 轮胎个数
    private Integer wheel;
    // 方向盘个数
    private Integer steering;
    // 油门个数
    private Integer acclerator;
    // 离合器个数
    private Integer clutch;
    // 柴油发动机
    private String dieselEngine;
    // 汽油发动机
    private String gasolineEngine;
    // 车载导航
    private String navigator;
    // 车顶棚
    private String top;
    
	// (篇幅原因这里省略各属性的setter/getter方法)
	// ......

    @Override
    public void info() {
        String desc = "这是一辆" + carType + ":\n" +
                wheel + "个车轮\n" +
                steering + "个方向盘\n" +
                acclerator + "个油门\n" +
                clutch + "个离合器\n" +
                "柴油发动机:" + dieselEngine + "\n" +
                "汽油发动机:" + gasolineEngine + "\n" +
                "车载导航:" + navigator + "\n" +
                "车顶棚:" + top + "\n";
        System.out.println(desc);
    }

抽象和具体生成器类:

/**
 * 具体生成器类1:保时捷生成器
 */
public class PoscheBuilder implements Builder {
    private Posche posche = new Posche();

    @Override
    public void installSteering(Integer steering) {
        posche.setSteering(steering);
    }

    @Override
    public void installWheel(Integer wheel) {
        posche.setWheel(wheel);
    }

    @Override
    public void installAccelerator(Integer accelerator) {
        posche.setAcclerator(accelerator);
    }

    @Override
    public void installClutch(Integer clutch) {
        posche.setClutch(clutch);
    }

    @Override
    public void installDieselEngine(String dieselEngine) {
        posche.setDieselEngine(dieselEngine);
    }

    @Override
    public void installGasolineEngine(String gasolineEngine) {
        posche.setGasolineEngine(gasolineEngine);
    }

    @Override
    public void installNavigator(String navigator) {
        posche.setNavigator(navigator);
    }

    @Override
    public void installTop(String top) {
        posche.setTop(top);
    }

    @Override
    public Car getCar() {
        posche.carType = "保时捷";
        return this.posche;
    }
}

/**
 * 具体生成器类2:五菱宏光生成器
 */
public class WulingBuilder implements Builder {
    private Wuling wuling = new Wuling();

    @Override
    public void installSteering(Integer steering) {
        wuling.setSteering(steering);
    }

    @Override
    public void installWheel(Integer wheel) {
        wuling.setWheel(wheel);
    }

    @Override
    public void installAccelerator(Integer accelerator) {
        wuling.setAcclerator(accelerator);
    }

    @Override
    public void installClutch(Integer clutch) {
        wuling.setClutch(clutch);
    }

    @Override
    public void installDieselEngine(String dieselEngine) {
        wuling.setDieselEngine(dieselEngine);
    }

    @Override
    public void installGasolineEngine(String gasolineEngine) {
        wuling.setGasolineEngine(gasolineEngine);
    }

    @Override
    public void installNavigator(String navigator) {
        wuling.setNavigator(navigator);
    }

    @Override
    public void installTop(String top) {
        wuling.setTop(top);
    }

    @Override
    public Car getCar() {
        wuling.carType = "五菱宏光";
        return this.wuling;
    }
}

主管类(核心部分):

/**
 * 主管类
 * 主管类可以理解成是生成器的指挥者,指挥生成器调用某些步骤,以及调整不同步骤的顺序等
 */
public class CarDirector {
    // 生产保时捷的详细步骤和顺序
    public void producePosche(Builder builder){
        builder.installWheel(4);
        builder.installSteering(1);
        builder.installAccelerator(1);
        builder.installGasolineEngine("高端汽油发动机");
        builder.installNavigator("高端车载导航");
    }

    // 生产五菱宏光的详细步骤和顺序
    public void produceWuling(Builder builder){
        builder.installWheel(4);
        builder.installSteering(1);
        builder.installAccelerator(1);
        builder.installClutch(1);
        builder.installGasolineEngine("国产汽油发动机");
        builder.installTop("一块铁板");
    }
}

最后看下客户端如何调用:

/**
 * 获得一辆汽车(具体产品),客户需要主管和具体生成器,无需知道生产汽车的具体过程和细节
 */
public class client {
    public static void main(String[] args) {
        /**
         * 获取主管类(“拿起生成器说明书并操作生成器”)
         */
        CarDirector director = new CarDirector();
        /**
         * 制造保时捷
         */
        PoscheBuilder poscheBuilder = new PoscheBuilder();
        // 主管类操作保时捷生成器,在生成卡车前先进行一些安装工作
        director.producePosche(poscheBuilder);
        // 设置完成后,生产我的保时捷
        Posche myPosche = (Posche) poscheBuilder.getCar();
        // 查看保时捷成品
        myPosche.info();
        /**
         * 制造五菱宏光
         */
        WulingBuilder wulingBuilder = new WulingBuilder();
        // 主管类操作五菱宏光生成器,在生成卡车前先进行一些安装工作
        director.produceWuling(wulingBuilder);
        // 设置完成后,生产你的五菱宏光
        Wuling yourWuling = (Wuling) wulingBuilder.getCar();
        // 查看五菱宏光成品
        yourWuling.info();

    }
}

生成器模式总结

  1. 产品(对象)生成具有滞后性。与工厂模式中的工厂不同,生成器模式中的“生成器”并不负责生产最终的产品,最终的产品是在“主管”手中生成的。
  2. 生成器干了点什么?在本文的故事背景中,生成器在生产汽车前,准备好了所有零件、实现了每一个步骤。
  3. 主管类干了点什么?主管指挥着生成器,组装出最后的汽车产品。当然主管要有宏观把控的能力,造不同的汽车分别需要哪些步骤,这些步骤是怎样的执行顺序,都是主管类实现的(想想你的大leader,是不是每天指挥程序猿就行了,早就不用自己写代码了?)。
  4. 抽象产品类:可以有,但没必要。本文的栗子中两个具体产品都继承自同一抽象产品,给人一种错觉:生成器模式也是要生产同一系列。事实上生成器模式的目的不是生产同一系列的产品,只要这些产品的属性或者生成过程相似,就可以用生成器模式。

共同学习,欢迎交流!
这里是源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值