03 Javascript创建型设计模式之 - 工厂模式
待兔 134 3

什么是工作模式?

工厂是用来干嘛的? 毫无疑问,工厂就是用来生产东西的

对于 js 的工厂模式来说,就是为了创建对象用的 上一节我们了解了单例模式,单例模式的特点是全局唯一 那么工厂模式就是为了生产大量产品用的

在大量创建对象的时候,会用到工厂模式

工厂模式的分类

一 简单工厂模式

生成少量的产品用到这种方法,很简单,就是在类的里面,通过 if 判断,不同条件,new 一个不同的对象返回就行了

我们以生成手机为例,如下代码


//手机的基类
class Phone {
    call(){
        console.log('我用手机打电话')
    }
}

//小米手机
class XiaoMiPhone extends Phone {
    call(){
        console.log('我用小米手机打电话')    
    }
}

//苹果手机
class ApplePhone extends Phone {
    call(){
        console.log('我用苹果手机打电话')
    }
}

我们来创建一个工厂类,专门生成手机的工厂类,代码如下

// 有了上面的产品类定义后,我们如果生成这些手机怎么做?
// 当然需要建一个生成手机的工厂类了
class PhoneFactory{

    //根据不同的类型,创建不同的手机,也就是所谓的工厂生成的产品
    produce(type){
        if(type === 'xiaomi'){
            return new XiaoMiPhone()
        } else if (type == 'apple') {
            return new ApplePhone()
        } else {
            return new Phone()
        }
    }
}

可以看到我们建了一个 PhoneFactory类,从字面意思就知道,是生成手机的工厂 这就是简单的工厂模式

二 工厂方法模式

为什么叫工厂方法模式,关键在于“方法”,因为工厂方法模式中,工厂类中有许多的方法用来生产不同的手机,不同于简单工作模式(工厂中只有一个生产方法),工厂方法模式中,工厂类中有许多的方法用来生产不同的产品的,工厂类的代码如下

// 和上面简单工厂模式不一样的是,工厂方法模式中,工厂类中有很多的方法创建不同的手机
// 而上面的简单工厂模式只有一个方法,在方法里面通过不同的 if 条件来创建不同的手机
// 重点在于 方法 这个词上
class PhoneFactory{

    //专门生产小米手机的方法
    produceXiaoMiPhone(){
        return new XiaoMiPhone()
    }

    //专门生产苹果手机的方法
    produceApplePhone(){
        return new ApplePhone()
    }
}

工厂类中有很多专用的方法来生产产品,怎么用呢?如下

//创建一个工厂对象 
let factory = new PhoneFactory()

//调用工厂对象创建不同的产品
let xiaomiPhone = factory.produceXiaoMiPhone()
let applePhone = factory.produceApplePhone()

//调用
xiaomiPhone.call()
applePhone.call()

上面的代码其实还可以再优化的,上面的可以优化的点在于:每次创建不同产品的时候,必须先要创建一个工厂对象

我们是不是可以优化一下,把生产不同产品的方法,设置为静态的,这样的话,我们生产不同的手机的话,就不需要再先创建一个工厂对象了

代码优化如下

//工厂类
class PhoneFactory{

    //专门生产小米手机的方法
    //设置为 static
    static produceXiaoMiPhone(){
        return new XiaoMiPhone()
    }

    //专门生产苹果手机的方法
    //设置为 static
    static produceApplePhone(){
        return new ApplePhone()
    }
}

//直接调用工厂的静态方法来生产不同的手机
let xiaomiPhone = PhoneFactory.produceXiaoMiPhone()
let applePhone = PhoneFactory.produceApplePhone()

//调用
xiaomiPhone.call()
applePhone.call()

经过上面的优化,就不用每次都先创建工厂对象了,这样我们就省了一步 使代码更简洁了

抽象工厂模式

学习了上面2种工厂模式之后,会不会有个疑问呢? 现在生活中,一个工厂也许只生产一种手机,假如苹果的工厂,只生成苹果手机,不生成小米手机,同样的,小米工厂只生成小米手机,不生成苹果手机

那么这种情况下怎么办呢?上面2种模式就不再适合了

这个时候就需要我们的抽象工厂模式了

什么是抽象工厂模式? 说白了,就是每个工厂只生产一种产品 比如有一个工厂叫 AppleFactory, 只生成苹果手机 比如有一个工厂叫 XiaoMiFactory,只生成小米手机


//只生产小米手机的工厂
class XiaoMiFactory {
    produce(){
        return new XiaoMiPhone()
    }
}


function producePhone(){
    //苹果工厂对象 ,生产苹果手机
    let appleFactory = new AppleFactory()
    let applePhone = appleFactory.produce()


    //小米工厂对象,生产小米手机
    let xiaoMiFactory = new XiaoMiFactory()
    let xiaomiPhone = xiaoMiFactory.produce()
}

producePhone()

通过工厂模式,我们来解释一下设计模式的六大原则之 对扩展开放,对修改关闭

什么意思? 对修改关闭,就是我现在要新加一个生产华为手机的需求

  • 对于简单工厂:我们只需要在原有的代码上添加一句 if (type === 'huawei') { } 就行了

  • 对于工厂方法:我们只需要在工厂类中添加一句 produceHuaweiPhone(){ } 就行了

上面2种方法,都需要在原有的代码基础上进行修改,才能实现,这样是不是很容易出错,比如程序员不小心写成了 if (type === 'huaweiiii') { }huawei单词拼错了,写成了huaweiiii,那用的人是不是要抓狂。

添加一个功能,需要修改原来的代码才能实现,这种就容易出错 对修改关闭的意思就是:添加一个功能,不需要修改原来的代码,也能实现

不修改原来的代码怎么实现呢?对了,就是抽象工厂方法,直接新建一个文件,里面添加一个工厂类就行了,没有修改原来的代码,还扩展了功能,还没有修改原来的代码 这就是对扩展开放,这样注不容易出错

因为js是弱类型语言,如果用java语言更容易演示这个原则,有兴趣的话大家可以看看java的实现,不过都差不多

评论区

索引目录