一天一个设计模式之JS实现——工厂模式

参考文章:
深入理解java三种工厂模式
工厂模式,工厂方法模式,抽象工厂模式 详解

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

工厂模式根据工厂抽象级别分为三种:
1、简单工厂模式
2、工厂方法模式
3、抽象工厂模式

工厂模式的角色一般有以下几个:
1、抽象工厂类(注:简单工厂无此类)
2、具体工厂类
3、抽象产品类
4、具体产品类

简单工厂模式

class BMW {
    drive() {
        console.log('drive bmw...');
    }
}
class Benz {
    drive() {
        console.log('drive Benz...');
    }
}
class Factory {
    getBMWCar() {
        return new BMW();
    }
    getBenzCar() {
        return new Benz();
    }
}

var f1 = new Factory();
f1.getBMWCar().drive();
f1.getBenzCar().drive();

当需要添加一类产品时,需要在工厂里添加对应的生产逻辑,违背了开闭原则,简单工厂模式只在非常简单的情况下使用。

工厂方法模式

由于简单工厂的弊端明显,更多时候使用到的是工厂方法模式,工厂方法模式把生产过程下放到派生类,所以当添加一类产品的时候只需添加一个工厂,扩展性增强。

注:由于JS没有接口也没有抽象类的说法,用以下的形式模拟。

class FactoryInterface {
    constructor() {
        if (Object.getPrototypeOf(this) === FactoryInterface.prototype) {
            throw new Error('该类是抽象类,无法实例化')
        }
    }
    getCar() {
        throw new Error('派生类必须实现该方法,抽象函数无法直接调用!');
    }
}   
class BMWFactory extends FactoryInterface {
    getCar() {
        return new BMW();
    }
}
class BenzFactory extends FactoryInterface {
    getCar() {
        return new Benz();
    }
}
var bmwF = new BMWFactory();
var benzF = new BenzFactory();
bmwF.getCar().drive();
benzF.getCar().drive();

抽象工厂模式

抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象。而且使用抽象工厂模式还要满足以下条件:
1.系统中有多个产品族,而系统一次只可能消费其中一族产品
2.同属于同一个产品族的产品以其使用。
举个例子,宝马和奔驰两个牌子都有越野车和商务车,宝马系的是一个产品族,奔驰系的也是一个产品族,每个产品族下面都有相类似的产品。

class SportsCar {
    constructor() {
        if (Object.getPrototypeOf(this) === SportsCar.prototype) {
            throw new Error('该类是抽象类,无法实例化')
        }
    }
    crossCountry() {
        throw new Error('派生类必须实现该方法,抽象函数无法直接调用!');
    }
}
class BussinessCar {
    constructor() {
        if (Object.getPrototypeOf(this) === BussinessCar.prototype) {
            throw new Error('该类是抽象类,无法实例化')
        }
    }
    talkBusiness() {
        throw new Error('派生类必须实现该方法,抽象函数无法直接调用!');
    }
}
class BMWSportsCar extends SportsCar {
    crossCountry() {
        console.log('宝马去越野');
    }
}
class BenzSportsCar extends SportsCar {
    crossCountry() {
        console.log('奔驰去越野');
    }
}
class BMWBussinessCar extends BussinessCar {
    talkBusiness() {
        console.log('宝马去谈生意');
    }
}
class BenzBussinessCar extends BussinessCar {
    talkBusiness() {
        console.log('奔驰去谈生意');
    }
}
class AbstractFactory {
    constructor() {
        if (Object.getPrototypeOf(this) === AbstractFactory.prototype) {
            throw new Error('该类是抽象类,无法实例化')
        }
    }
    getSportsCar() {
        throw new Error('派生类必须实现该方法,抽象函数无法直接调用!');
    }
    getBussinessCar() {
        throw new Error('派生类必须实现该方法,抽象函数无法直接调用!');
    }
}

class BMWSoleFactory extends AbstractFactory {
    getSportsCar() {
        return new BMWSportsCar();
    }
    getBussinessCar() {
        return new BMWBussinessCar();
    }
}
class BenzSoleFactory extends AbstractFactory {
    getSportsCar() {
        return new BenzSportsCar();
    }
    getBussinessCar() {
        return new BenzBussinessCar();
    }
}

var benf2 = new BenzSoleFactory();
var bmwf2 = new BMWSoleFactory();
benf2.getSportsCar().crossCountry();
benf2.getBussinessCar().talkBusiness();
bmwf2.getSportsCar().crossCountry();
bmwf2.getBussinessCar().talkBusiness();

小结:
工厂模式的作用是解耦了产品的生产和使用部分,让使用需要的产品的时候只需要调用对应的接口即可,减少冗余代码。
优点:1、隐藏了生产过程,只需调用相应接口;2、扩展性好,当需要添加一类产品时,只需添加对应工厂类即可。
与建造者模式区别:工厂模式不需要客户端关心构建过程,只需要了解产品对应的工厂即可;建造者模式更多的是构建拥有复杂的内部结构的对象,过程由Derector控制。

    原文作者:设计模式
    原文地址: https://segmentfault.com/a/1190000014104914
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞