1 创建型-工厂模式

1.1 简单工厂模式

其实就是将创建对象的过程单独封装 ,同时它的应用场景也非常容易识别:有构造函数的地方,我们就应该想到简单工厂;在写了大量构造函数、调用了大量的 new、自觉非常不爽的情况下,我们就应该思考是不是可以掏出工厂模式重构我们的代码了

    // 给不同工种分配职责说明
    function User(name, age, career, work) {
        this.name = name;
        this.age = age;
        this.career = career;
        this.work = work;
    }
    
    function Factory(name, age, career) {
        let work;
        switch (career) {
            case 'coder': {
                work = ['写代码', '写系分', '修bug']
                break;
            }
            case 'product-manager': {
                work = ['订会议室', '写PRD', '催更']
                break;
            }
            case 'boss': {
                work = ['喝茶', '看报', '见客户']
                break;
            }
        }
        return new User(name, age, career, work)
    }
    
    const wang = new Factory('wang', 50, 'boss');
    const sun = new Factory('sun', 25, 'coder');
    const li = new Factory('li', 30, 'product-manager');
    
    console.log(wang)
    console.log(sun)
    console.log(li)

1.2 抽象工厂模式

    // 定义操作系统这类产品的抽象产品类
    class OS {
        constructor() {
            if (new.target === OS) {
                throw new Error('不能实例化抽象类');
            }
        }
    }
    
    // 定义具体操作系统的具体产品类
    class AndroidOS extends OS {
        constructor() {
            super();
        }
    
        controlHardware() {
            console.log('我会用安卓的方式去操作硬件');
        }
    }
    
    class AppleOS extends OS {
        constructor() {
            super();
        }
    
        controlHardware() {
            console.log('我会用苹果的方式去操作硬件');
        }
    }
    
    // 定义手机硬件这类产品的抽象产品类
    class Hardware {
        constructor() {
            if (new.target === Hardware) {
                throw new Error('不能实例化抽象类');
            }
        }
    
        // 手机硬件的共性方法,这里提取了“根据命令运转”这个共性
        operateByOrder() {
            throw new Error('抽象产品方法不允许直接调用,你需要将我重写!');
        }
    }
    
    // 定义具体硬件的具体产品类
    class QualcommHardware extends Hardware {
        constructor() {
            super();
        }
    
        operateByOrder() {
            console.log('我会用高通的方式去运转')
        }
    }
    
    class MiWare extends Hardware {
        constructor() {
            super();
        }
    
        operateByOrder() {
            console.log('我会用小米的方式去运转')
        }
    }
    
    class MobilePhoneFactory {
        // 提供操作系统的接口
        createOS() {
            throw new Error("抽象工厂方法不允许直接调用,你需要将我重写!");
        }
    
        // 提供硬件的接口
        createHardware() {
            throw new Error("抽象工厂方法不允许直接调用,你需要将我重写!");
        }
    }
    
    // 具体工厂继承自抽象工厂
    class FakeStarFactory extends MobilePhoneFactory {
        constructor() {
            super()
        }
    
        createOS() {
            // 提供安卓系统实例
            return new AndroidOS()
        }
    
        createHardware() {
            // 提供高通硬件实例
            return new QualcommHardware()
        }
    }
    
    // 这是我的手机
    const myPhone = new FakeStarFactory()
    // 让它拥有操作系统
    const myOS = myPhone.createOS()
    // 让它拥有硬件
    const myHardWare = myPhone.createHardware()
    // 启动操作系统(输出‘我会用安卓的方式去操作硬件’)
    myOS.controlHardware()
    // 唤醒硬件(输出‘我会用高通的方式去运转’)
    myHardWare.operateByOrder()

抽象工厂和简单工厂的思路,思考一下:它们之间有哪些异同?

  • 它们的共同点,在于都尝试去分离一个系统中变与不变的部分
  • 它们的不同在于场景的复杂度

在简单工厂的使用场景里,处理的对象是类,并且是一些非常好对付的类——它们的共性容易抽离,同时因为逻辑本身比较简单,故而不苛求代码可扩展性。抽象工厂本质上处理的其实也是类,但是是一帮非常棘手、繁杂的类,这些类中不仅能划分出门派,还能划分出等级,同时存在着千变万化的扩展可能性——这使得我们必须对共性 作更特别的处理、使用抽象类去降低扩展的成本,同时需要对类的性质作划分

Last Updated:
Contributors: leeguooooo