首先须要说一下工厂模式。工厂模式根据抽象程度的不一样分为三种数据库
简单工厂模式:又称为静态工厂方法模式,它属于类建立型模式。
在简单工厂模式中,能够根据参数的不一样返回不一样类的实例。
由工厂对象决定建立某一种产品对象类的实例。缓存
// #简单工厂模式第一种 /** * 足球类 */ var FootBall = function () { this.play = function () { console.log('我在踢足球'); } } /** * 篮球类 */ var BasketBall = function () { this.play = function () { console.log('我在打篮球'); } } var football = new FootBall(); football.play(); var basketball = new BasketBall(); basketball.play(); /** * 球类工厂 */ var Ball = function(name) { switch (name) { case '足球': return new FootBall(); break; case '篮球': return new BasketBall(); break; } } var football = Ball('足球'); football.play(); var basketball = Ball('篮球'); basketball.play(); // #简单工厂模式第一种end
这段案例能够简单的这么去理解,假设咱们须要多个球,咱们但愿在使用球的时候,只须要告诉管理员咱们须要的球的类型,不须要一个个去找对应的球这个管理员就相对于工厂函数。安全
简单讲就是使用简单工厂模式,那么你就不须要关心它的具体实现,你只须要知道你要使用的类型,那么工厂函数会自动帮你去作对应的事情函数
// #简单工厂模式第二种 /** * 球类工厂 */ var Ball = function(name) { // 建立一个对象,对对象扩展扩展属性还有方法 var o = new Object(); o.name = name; //默认的方法 若是在加上一个羽毛球类,这时候就不须要补充play方法 o.play = function () { console.log('我在打'+name); } if (name === '足球') { o.play = function () { console.log('我在踢'+name); } }else if (name === '篮球') { o.play = function () { console.log('我在打'+name); } } // 将对象返回 return o; } var football = Ball('足球'); football.play(); var basketball = Ball('篮球'); basketball.play(); // #简单工厂模式第二种end
这段案例是用对象的方式代替多个类,把相同点抽离出来,this
不一样点在一一作类型判断,这样也是简单工厂模式实现的另外一种方式prototype
简单工厂模式的优势:设计
简单工厂模式的缺点code
简单工厂模式的适用状况对象
在如下状况下可使用简单工厂模式:继承
简单工厂模式总结
工厂方法模式:又称为工厂模式,也叫虚拟构造器模式或者多态工厂模式它属于类建立型模式。在工厂方法模式中,工厂父类负责定义建立产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样作的目的是将产品类的实例化操做延迟到工厂子类中完成,即经过工厂子类来肯定究竟应该实例化哪个具体产品类这样解释可能会有点抽象。
// # 工厂方法模式 // 安全模式建立工厂类 var Ball = function (type,name) { /** * 安全模式 Ball也能够运行处new Ball的效果 */ if(this instanceof Ball) { var s = new this[type](name); return s; }else { return new Ball(type,name); } } // 工厂原型中设置建立全部类型数据对象的基类 Ball.prototype = { basketBall: function(name) { this.play = function() { console.log('我在打'+name); } }, footBall: function(name) { this.play = function() { console.log('我在踢'+name); } }, badmintonBall: function(name) { this.play = function() { console.log('我在打'+name); } }, // .... } var football = new Ball('footBall','足球'); football.play(); var basketball = new Ball('basketBall','篮球'); basketball.play(); var badmintonball = new Ball('badmintonBall','羽毛球'); badmintonball.play(); // # 工厂方法模式end
这段案例是这么去理解的,咱们先建立一个球类工厂,这个球类工厂是一个抽象的,不作具体的实现,而后咱们在这个球类工厂里面在去定义对应的球类实现,如篮球,羽毛球,足球等实现,在工厂方法模式中,抽象类工厂只是负责定义一个对外的公共接口,而工厂子类则负责生成具体的产品对象。
这样作的目的是将产品类的实例化操做延迟到工厂子类中完成,即经过工厂子类来肯定究竟应该实例化哪个具体产品类若是这时候在出现一个新的球类运动,只须要为这种新类型的球类建立一个具体的球类实现就能够,这一特色无疑使得工厂方法模式具备超越简单工厂模式的优越性,更加符合“开闭原则”
上面案例包含了一个安全模式的知识点
// 安全模式建立工厂类 var Ball = function (type,name) { /** * 安全模式 Ball也能够运行处new Ball的效果 */ if(this instanceof Ball) { var s = new this[type](name); return s; }else { return new Ball(type,name); } }
这段代码主要解决的问题是,有些同窗使用工厂类的时候,忘记使用关键字new,得不到预期想要的效果这边的解决方案就是,在构造函数开始时先判断当前对象this指代是否是当前工厂类,若是不是则经过new关键字建立对象返回,这样就能够实现不使用new关键词也能够达到相同的效果了
工厂方法模式的优势:
工厂方法模式的缺点:
工厂方法模式的适用状况
在如下状况下可使用工厂方法模式:
工厂方法模式总结
工厂方法模式是简单工厂模式的进一步抽象和推广。因为使用了面向对象的多态性,工厂方法模式保持了简单工厂模式的优势,并且克服了它的缺点。在工厂方法模式中,核心的工厂类再也不负责全部产品的建立,而是将具体建立工做交给子类去作。这个核心类仅仅负责给出具体工厂必须实现的接口,而不负责产品类被实例化这种细节,这使得工厂方法模式能够容许系统在不修改工厂角色的状况下引进新产品。
工厂方法模式的主要优势是增长新的产品类时无须修改现有系统,并封装了产品对象的建立细节,系统具备良好的灵活性和可扩展性;其缺点在于增长新产品的同时须要增长新的工厂,致使系统类的个数成对增长,在必定程度上增长了系统的复杂性。
抽象工厂模式:经过对类的工厂抽象使其业务用于对产品类簇的建立,而不是负责建立某一类产品的实例,属于对象建立型模式。
抽象类一直出如今咱们的文章中,那么这边先来解释一下什么是抽象类
抽象类是一种声明但不能使用的类,当你使用时就会报错,在JavaScript中abstract仍是一个保留字,因此目前来讲还不能像
传统面向对象语言那么轻松的去建立抽象类.
不过JavaScript有本身的实现方式,能够模拟出抽象类
来一段代码
// 抽象类的介绍 var Ball = function () {} Ball.prototype = { play: function () { return new Error('抽象方法不能调用'); } }
解释:
咱们能够看到建立的Ball类其实什么都不能作,建立时没有任何属性,原型定义的方法也不能使用,不然就会报错。可是在继承上倒是颇有用的,
由于定义了一种类,并定义了该类所具有的方法,若是没有在子类中重写这写方法,那么调用的时候就会报错。
这一特色能够很好的提醒子类去重写这一方法,否则会在调用的时候提示错误那么在了解了什么是抽象类的状况下,咱们在来比较一下工厂方法模式与抽象工厂模式的不一样点,以方便咱们更好的去理解抽象工厂模式
工厂方法模式与抽象工厂模式的对比
在工厂方法模式中具体工厂负责生产具体的产品,每个具体工厂对应一种具体产品,工厂方法也具备惟一性,通常状况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方法。可是有时候咱们须要一个工厂能够提供多个产品对象,而不是单一的产品对象。
为了更清晰地理解抽象工厂模式,须要先引入两个概念:
海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中。
抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则须要面对多个产品等级结构,一个工厂等级结构能够负责多个不一样产品等级结构中的产品对象的建立。当一个工厂等级结构能够建立出分属于不一样产品等级结构的一个产品族中的全部对象时,抽象工厂模式比工厂方法模式更为简单、有效率。
这句话比较简单的理解方式就是:若是一个工厂只须要生产一个类型的产品好比说电视机,那么用工厂方法模式是比较合理的,若是这个工厂又须要成产电视机,又须要生产冰箱之类的,那么这时候用工厂抽象模式就是最合适的。
// # 抽象工厂模式 var Sport = function(subType, superType) { if( typeof Sport[superType] === 'function'){ // 缓存类 function F() {}; // 继承父类属性和方法 F.prototype = new Sport[superType](); // 将子类constructor 指向子类 subType.constructor = subType; // 子类原型继承 “父类” subType.prototype = new F(); }else { // 不存在抽象类则抛出错误 throw new Error('未建立该抽象类'); } } // 球类运动抽象类 Sport.Ball = function () { this.type = 'ball'; } Sport.Ball.prototype = { play: function () { return new Error('抽象方法不能调用'); } } // 力量型运动抽象类 Sport.Power = function () { this.type = 'power'; } Sport.Power.prototype = { play: function () { return new Error('抽象方法不能调用'); } } // 速度型运动抽象类 Sport.Speed = function () { this.type = 'speed'; } Sport.Speed.prototype = { play: function () { return new Error('抽象方法不能调用'); } } // 篮球类 var BasketBall = function (name) { this.name = name; }; // 抽象工厂实现对球类运动的继承 Sport(BasketBall,'Ball'); BasketBall.prototype.play = function () { console.log('我在玩'+this.name); } // 举重类 var WeightLifting = function (name) { this.name = name; }; // 抽象工厂实现对力量型运动的继承 Sport(WeightLifting,'Power'); WeightLifting.prototype.play = function () { console.log('我在玩'+this.name); } // 跑步类 var Running = function (name) { this.name = name; }; // 抽象工厂实现对速度运动的继承 Sport(Running,'Speed'); Running.prototype.play = function () { console.log('我在'+this.name); } // 抽象工厂模式实现 var basketBall = new BasketBall('篮球'); console.log(basketBall.type);//ball basketBall.play(); var weightLifting = new WeightLifting('举重'); console.log(weightLifting.type);//power weightLifting.play(); var running = new Running('跑步'); console.log(running.type);//ball running.play(); /** 输出结果 * ball * 我在玩篮球 * power * 我在玩举重 * speed * 我在跑步 */ // # 抽象工厂模式end
这段栗子先是建立一个运动类的抽象工厂,经过这个暴露外部调用的接口,传递2个参数,一个是subType,当前实例化的对象,也就是子类,
一个是superType,须要继承的父类(抽象类)的名称,在工厂函数中实现了子类对父类的继承。
在继承过程当中有一个地方须要注意,就是在对过渡类继承的时候,咱们不是继承父类原型,而是经过new关键字复制父类的一个实列,这样作的目的是过渡类不只仅继承父类的原型方法,还须要继承父类的对象属性,因此经过new关键字的方式实现了继承。
而后经过在抽象工厂类上面进行扩展对应的抽象类,也就是咱们须要经过继承的父类,我这边添加了3个抽象类Ball,Power,Speed,分别给抽象类指定了type属性,还有方法play,既然建立了抽象类,那么下面就是开始使用抽象工厂去建立子类,这边分别对Ball,Power,Speed 3个抽象类进行了实现建立了BasketBall(球类),WeightLifting(力量),Running(速度)3个子类3个子类分别对play方法进行了实现最后就是对于子类的调用实现,在实现子类调用的时候,
咱们能够获取到继承的父类当中对应的type
抽象工厂模式的优势:
当一个产品族中的多个对象被设计成一块儿工做时,它可以保证客户端始终只使用同一个产品族中的对象。
增长新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。
抽象工厂模式的缺点:
开闭原则的倾斜性(增长新的工厂和产品族容易,增长新的产品等级结构麻烦)。
增长新的产品等级结构:对于增长新的产品等级结构,须要修改全部的工厂角色,包括抽象工厂类,在全部的工厂类中都须要增长生产新产品的方法,不能很好地支持“开闭原则”。
抽象工厂模式的适用状况:
在如下状况下可使用抽象工厂模式:
抽象工厂模式总结
注:根据实际适用状况去选择对应的工厂模式