浅析一下设计模式中的建造者模式

112 阅读4分钟

建造者模式

什么是建造者模式?

建造者模式就是把一个很复杂的东西,拆分成相对多个简单的部分,然后通过需求分别建造他们,最后组合成该复杂的东西。听起来是不是有点官方了,那就换成大白话举个例子,我想买个电脑,你可以选择配置好的,也可以选择自己配一台电脑,那么一台电脑就是所说的相对复杂的东西,自己配部件就是拆分成多个简单的部分,最后把配件组合到一起形成一台电脑叫做根据需求建造简单的部分组合成复杂的东西,这就是建造者模式

废话不多说上代码

123

//我们来写个组装电脑的例子

class Build {
    constructor() {
        this.monitor = "暂无配置";
        this.CPU = "暂无配置";
        this.RAM = "暂无配置";
        this.opticalDrive = "暂无配置";
        this.keyboard = "暂无配置";
        this.mouse = "暂无配置";
    }
	//建造显示屏
    addMonitor(monitor) {
        this.monitor = monitor;
        return this;
    }
    //建造cpu
    addCpu(cpu) {
        this.CPU = cpu;
        return this;
    }
    //建造内存
    addRam(ram) {
        this.RAM = ram;
        return this;
    }
    //建造光驱
    addOpticalDrive(opticalDrive) {
        this.opticalDrive = opticalDrive;
        return this;
    }
    //建造键盘
    addKeyboard(keyboard) {
        this.keyboard = keyboard;
        return this;
    }
    //建造鼠标
    addMouse(mouse) {
        this.mouse = mouse;
        return this;
    }

    //组合部件
    build() {
        return {
            monitor: this.monitor,
            CPU: this.CPU,
            RAM: this.RAM,
            opticalDrive: this.opticalDrive,
            keyboard: this.keyboard,
            mouse: this.mouse,
        };
    }
}

//我们来自由搭配一下
const computer = new Build()
    .addMonitor("5k高清显示屏")
    .addCpu("3.00GHz")
    .addRam("16G")
    .addOpticalDrive("外置光驱")
    .addKeyboard("机械键盘")
    .addMouse("雷蛇鼠标")
    .build();

console.log(computer);
/* 
    {monitor: "5k高清显示屏", cpu: "3.00GHz", ram: "16G", opticalDrive: "外置光驱", keyboard: "机械键盘", …}
    cpu: "3.00GHz"
    keyboard: "机械键盘"
    monitor: "5k高清显示屏"
    mouse: "雷蛇鼠标"
    opticalDrive: "外置光驱"
    ram: "16G"
    __proto__: Object
*/

上面就通过我 Build 这个创建者类的写法和调用方法,通过拆分各个零件最后通过build的方法将它们组装形成了自己想要的电脑,但是有个缺陷,一台电脑当然不止我所写的6个部件组成,他肯定还有散热器,显卡,音响。。。等等等,那我们要在class下面一直加方法么?当然也是可以的,不过就会显得非常的臃肿,所以我们也可以通过自动构建的方式去创建类里面的 addxxxx方法来优化代码。

// 优化版本
class Build {
    constructor() {
        this.monitor = "暂无配置";
        this.cpu = "暂无配置";
        this.ram = "暂无配置";
        this.opticalDrive = "暂无配置";
        this.keyboard = "暂无配置";
        this.mouse = "暂无配置";
		
        //通过object的方法得到键名
        Object.keys(this).forEach((key) => {
            //统一生成方法名
            const addName = `add${key
                .substring(0, 1)
                .toUpperCase()}${key.substring(1)}`;
            //统一执行方法
            this[addName] = (val) => {
                this[key] = val;
                return this;
            };
        });
    }
    //建造
    build() {
        const keyNotAdd = Object.keys(this).filter(
            (key) => typeof this[key] !== "function"
        );
        return keyNotAdd.reduce((val, key) => {
            return {
                ...val,
                [key]: this[key],
            };
        }, {});
    }
}

// 我们来自由搭配一下;
const computer = new Build()
    .addMonitor("5k高清显示屏")
    .addCpu("3.00GHz")
    .addRam("16G")
    .addOpticalDrive("外置光驱")
    .addKeyboard("机械键盘")
    .addMouse("雷蛇鼠标")
    .build();
console.log(computer);
/* 
    {monitor: "5k高清显示屏", cpu: "3.00GHz", ram: "16G", opticalDrive: "外置光驱", keyboard: "机械键盘", …}
    cpu: "3.00GHz"
    keyboard: "机械键盘"
    monitor: "5k高清显示屏"
    mouse: "雷蛇鼠标"
    opticalDrive: "外置光驱"
    ram: "16G"
    __proto__: Object
*/

这样我们就实现了代码的优化,我们在想添加其他配件的时候,只需要在constructor下加属性就可以了,然后通过add属性名来建造他。

可是问题又来了,我们不能建造一个东西就写一个建造函数吧,这只是电脑,那我们还想建造房子,车子等种种的东西,我们该怎么写呢?

//我们可以先创建一个父类
class Build {
    //初始化
    init() {
        Object.keys(this).forEach((key) => {
            //统一生成方法名
            const addName = `add${key
                .substring(0, 1)
                .toUpperCase()}${key.substring(1)}`;
            //统一执行方法
            this[addName] = (val) => {
                this[key] = val;
                return this;
            };
        });
    }
    //建造
    build() {
        const keyNotAdd = Object.keys(this).filter(
            (key) => typeof this[key] !== "function"
        );

        return keyNotAdd.reduce((val, key) => {
            return {
                ...val,
                [key]: this[key],
            };
        }, {});
    }
}

// 通过子类继承父方法的性质去写

// 子类1:创建电脑
class BuildComputer extends Build {
    constructor() {
    	//继承
        super();
        this.monitor = "";
        this.cpu = "";
        this.ram = "";
        this.opticalDrive = "";
        this.keyboard = "";
        this.mouse = "";
        //用父类的方法
        super.init();
    }
}

// 子类2:创建汽车
class BuildCar extends Build {
    constructor() {
    	//继承
        super();
        this.engine = "";
        this.chassis = "";
        this.body = "";
        //用父类的方法
        super.init();
    }
}

// 建造电脑
const computer = new BuildComputer()
    .addMonitor("5k高清显示屏")
    .addCpu("3.00GHz")
    .addRam("16G")
    .addOpticalDrive("外置光驱")
    .addKeyboard("机械键盘")
    .addMouse("雷蛇鼠标")
    .build();
console.log(computer);
/* 
    {monitor: "5k高清显示屏", cpu: "3.00GHz", ram: "16G", opticalDrive: "外置光驱", keyboard: "机械键盘", …}
    cpu: "3.00GHz"
    keyboard: "机械键盘"
    monitor: "5k高清显示屏"
    mouse: "雷蛇鼠标"
    opticalDrive: "外置光驱"
    ram: "16G"
    __proto__: Object
*/

// 建造汽车
const car = new BuildCar()
    .addEngine("v12发动机")
    .addChassis("复合材料底盘")
    .addBody("碳纤维车身")
    .build();
console.log(car);
/* 
    {engine: "v12发动机", chassis: "复合材料底盘", body: "碳纤维车身"}
    body: "碳纤维车身"
    chassis: "复合材料底盘"
    engine: "v12发动机"
    __proto__: Object
 */

有点东西

这是我第一次写文章,文采不太好,也不知道怎么引入图,哈哈哈 ,大家将就看吧,有问题欢迎大家指出相互交流学习。溜了溜了