前言

后面的文章中提到一个设计准则——针对接口编程,不针对实现编程,那必定有人会问,实例化对象的时候不就是在针对实现编程了么?的确如此,实例化这个流动常常造成“耦合”问题,因而实例化流动不应该总是公开地进行。那么怎么能力更加的松耦合的进行开发呢?那么就是本篇文章的主题——工厂模式。

简略工厂模式

假如你要制作一个披萨点餐零碎,那么你的代码可能是这么写的。

function orderPizza () {    let pizza = new Pizza();    pizza.prepare();    pizza.bake();    pizza.cut();    pizza.box();    return pizza;}

然而当你须要更多的披萨类型,须要减少肯定的代码来判断制作哪种披萨,于是减少了一段判断的代码。

function orderPizza (type) {    let pizza;    if (type === 'a') {       pizza = new aPizza();     } else if(type === 'b') {        pizza = new bPizza();     ) else {        pizza = new cPizza();     }   ...}

然而实际上披萨类型并没有那么少,并且随着工夫的扭转,品种也可能删除,所以依据之前提到的设计准则——类应该对扩大凋谢,对设计敞开,因而咱们须要对那些会扭转和不会扭转的局部进行封装。

class PizzaStore {    factory = null;    constructor (factory) {        this.factory = factory;    }    orderPizza (type) {        let pizza = this.factory.createPizza(type);        pizza.prepare();        pizza.bake();        pizza.cut();        pizza.box();        return pizza;    }}class SimplePizzaFactory {    createPizza (type) {        let pizza;        if (type === 'a') {           pizza = new aPizza();         } else if(type === 'b') {            pizza = new bPizza();         ) else {            pizza = new cPizza();         }        return pizza;    }}

通过将创立披萨逻辑抽离进来,失去了一个专门用来生产对象的办法,咱们将其称之为工厂。有了工厂当前,orderPizza就不关怀具体的生产对象的过程,只须要你返回一个披萨给我。这样做还有什么益处呢?首先是这个工厂办法是能够复用的,不光是能够用在orderPizza这个办法里,只有是须要生产对象的中央都能够应用这个工厂,而批改的时候也只须要批改工厂。

上述的办法其实叫做简略工厂,其实简略工厂不是一个设计模式,而更像一种编程习惯,然而这种办法经常被应用,因此有些开发人员的确会误会为工厂模式。然而不得不说,尽管不属于模式的一种,然而够用就行,开发的时候不须要时时刻刻都套用各种设计模式在其中,咱们其实只须要某种程度的“完满”就够了。

那么怎么样才是真正的工厂模式呢?

工厂模式

工厂办法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂办法让类把实例化推延到子类。

假如当初披萨开设不同地区的分店,因而风味将会有各种各样的差别。那么如果应用下面的简略工厂模式,会是怎么样呢?首先写出三种不同的工厂来继承SimplePizzaFactory,重写createPizza办法,别离是aFactory,bFactory,cFactory。

aStore = new PizzaStore(new aFactory());aStore.orderPizza('a');bStore = new PizzaStore(new bFactory());bStore.orderPizza('b');

这种写法看起来没什么问题,然而你可能会发现有人会不应用你设定的PizzaStore,开始应用借鉴的流程,导致标准失落。因而咱们须要须要建设一个更好的框架,使其具备更好的弹性,那么这里就要用到这次讲的模式——工厂模式来实现。

那么要做的事件就是要把createPizza办法放到PizzaStore外面,不过要把它设置成“形象办法”,而后为不同的分店建设子类。上面先看pizzaStore的扭转。

class PizzaStore {    orderPizza(type){        let pizza;        pizza = this.createPizza(type);        pizza.prepare();        pizza.bake();        pizza.cut();        pizza.box();        return pizza;    }    creatPizza () {} // 形象办法}

当初让PizzaStore的各个子类去负责定义本人的createPizza办法,这样就可能实现领有灵便的实现形式,同时又是建设在咱们设定的框架之下。先来实现一个分店的代码。

class aPizzaStore extends PizzaStore {    creatPizza (type) {        let pizza;        if (type === 'a') {           pizza = new aPizza();         } else if(type === 'b') {            pizza = new bPizza();         ) else {            pizza = new cPizza();         }        return pizza;    }}

能够看到orderPizza中的pizza在执行各种办法的时候,是不晓得哪只具体类参加了进来,换句话说,这就是“解耦”。

总结

工厂办法模式可能封装具体类型的实例化,pizzaStore中提供的createPizza创建对象的办法也叫做“工厂办法”。在pizzaStore类中可能还会有其余办法会用到这个办法,然而只有子类才真正的实现了这个办法并实例化对象。

看到这里应该还是会有人困惑简略工厂和工厂模式之间的差别,尽管它们的确很像,然而简略工厂是把全副事件都放在一个中央解决完了的办法。然而工厂模式却是先建设起来一个框架,让子类来决定实现。然而简略工厂不具备工厂办法的弹性,因为简略工厂不能变更正在创立的产品。