分类
工厂模式一般分为:简单工厂模式、工厂方法模式、抽象工厂模式。三种模式从上到下逐步抽象,一般也把简单工厂模式看为工厂方法模式的一种特例。
简单工厂
我们先分析一下简单工厂的UML图,途中有以下几个角色
- 工厂类角色(SimpleFactory):核心类根据逻辑不同,产生具体的工厂产品
- 抽象产品(AbstractProduct):它一般是具体产品继承的父类或者实现的接口。由接口或者抽象类来实现。
- 具体产品(ConcreteProduct):工厂类所创建的对象就是此角色的实例
假设当前的业务场景,需要对外提供通用的自定义提示Alert,Confirm,Prompt。三种提示都有通用的show方法。
// 抽象产品
class CommonNotice () {
show () {}
close () { // this function will close the notice for all instance}
}
// 具体产品1:Alert
class CommonAlert extends CommonNotice () {
show () {console.log('i am alert')}
}
// 具体产品2:Confirm
class CommonConfirm extends CommonNotice () {
show () {console.log('i am confirm')}
}
// 具体产品3:Confirm
class CommonPrompt extends CommonNotice () {
show () {console.log('i am Prompt')}
}
// 工厂类角色
function SimpleFactory (name) {
switch (name) {
case 'alert' return new CommonAlert();
case 'confirm' return new CommonConfirm();
case 'prompt' return new CommonPrompt();
}
}
// 使用工厂
var factoryClient = SimpleFactory('alert')
factoryClient.show() // this will call show funciton in CommonAlert
优点
- 简单工厂包含必要的判断逻辑,简单工厂实现了对象的创建和使用的分离。
- 客户端无需知道所创建的具体产品类的类名,只需要具体产品类对应的参数即可。
在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。
缺点
SimpleFactory的职责过重,它包含核心的逻辑判断语句,它一旦有问题,整个系统都要出问题。
- 在添加新的类的时候,SimpleFactory就要修改,违反了开放——封闭原则!这样及其不利于系统的扩展和维护。
工厂方法
简单工厂模式中存在一个问题,如果需要添加一个新的产品,那必须要修改SimpleFactory工厂类,一旦操作不当,在修改时就有可能引发更多的问题。参考开闭原则的规定,我们希望新的扩展不需要对原有的代码进行修改。
相比简单工厂模式,我们多了抽象工厂(AbstractFactory)和具体工厂(concreteFactory)
// 抽象产品
class CommonNotice {
show () {}
close () {
// this function will close the notice for all instance
}
}
// 具体产品1:Alert
class CommonAlert extends CommonNotice {
show () {console.log('i am alert')}
}
// 具体产品2:Confirm
class CommonConfirm extends CommonNotice {
show () {console.log('i am confirm')}
}
// 具体产品3:Confirm
class CommonPrompt extends CommonNotice {
show () {console.log('i am Prompt')}
}
// 抽象工厂
class AbstractFactory {
// 工厂方法
createProduct () {}
}
// 具体工厂1
class AlertFactory extends AbstractFactory {
createProduct () {
return new CommonAlert()
}
}
// 具体工厂2
class ConfirmFactory extends AbstractFactory {
createProduct () {
return new CommonConfirm()
}
}
// 具体工厂3
class PromptFactory extends AbstractFactory {
createProduct () {
return new CommonPrompt()
}
}
// 使用Alert 我们通过createProduct这个工厂方法来获取实际需要调用的对象实例
var client = (new AlertFactory()).createProduct()
client.show() // i am alert
// 如果添加了一个CommonMessage的实现
// 具体产品:Confirm
class CommonMessage extends CommonNotice {
show () {console.log('i am message')}
}
// 具体工厂
class MessageFactory extends AbstractFactory {
createProduct () {
return new CommonMessage()
}
}
// 使用
var client2 = (new MessageFactory()).createProduct()
client.show() // i am message
优点
- 工厂方法用来创建客户所需要的产品,同时隐藏了哪种具体产品类将被实例化的细节,用户只需要要关注工厂,不需要关注创建的细节。
在增加修改新的运算类的时候不用修改代码,只需要增加对应的工厂就好,完全符合开放——封闭性原则。
缺点
在增加新的产品时,也必须增加新的工厂类,会带来额外的开销
- 抽象层的加入使得理解程度加大
抽象工厂
抽象工厂封装类一组具有共同目标的单个工厂,比如alert、message、prompt、confirm都需要实现各自的show方法。它能够将一组对象的实现细节分离出来,允许多种对象类型一起工作。 ```javascript // 抽象工厂类 var AbstractFactory = (function () { var types = {} return { // 提供注册产品的方法 registerNotice: function (type, Notice) { var proto = Notice.prototype; // 只要具体产品实现了统一契约show方法即可 if (proto.show) {
} }, // 获取具体产品 getNotice: function (type) { var Notice = types[type]types[type] = Notice
} else {if (Notice) {
return new Notice()
} } } })(); AbstractFactory.registerNotice(‘Alert’, CommonAlert) AbstractFactory.registerNotice(‘Confirm’, CommonConfirm) AbstractFactory.registerNotice(‘Prompt’, CommonPrompt)return null
// client使用 AbstractFactory.getNotice(‘Alert’).show() AbstractFactory.getNotice(‘Confirm’).show() AbstractFactory.getNotice(‘Prompt’).show()
// 当后续需要扩展产品 // 新增具体产品 class CommonModal { show () { // modal show function } } AbstractFactory.registerNotice(‘Modal’, CommonModal)
优点
参考
[1]Addy Osmani著 徐涛译.JavaScript设计模式.北京:人民邮电出版社,2013,6
[2]https://blog.csdn.net/xiao1_1bing/article/details/81774931
[3]https://blog.csdn.net/jerry11112/article/details/80618420