js-工厂模式
首先需要说一下工厂模式。工厂模式根据抽象程度的不同分为三种
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
1.简单工厂模式
简单工厂模式:又称为静态工厂方法模式,它属于类创建型模式。
在简单工厂模式中,可以根据参数的不同返回不同类的实例。
由工厂对象决定创建某一种产品对象类的实例。
let Ball= function(name){
let A = new Object();
A.name = name;
A.play = function(){
console.log(`我在打${name}`)
}
return A
}
let football = Ball('足球');
console.log(football)
football.play(); // 我在打足球
let basketball = Ball('篮球');
basketball.play() // 我在打篮球
这段案例可以这么去理解,假设我们需要多个球,我们希望在使用球
的时候,只需要告诉管理员我们需要的球的类型,不需要一个个去找对应的球
这个管理员就相对于工厂函数。
简单讲就是使用简单工厂模式,那么你就不需要关心它的具体实现,
你只需要知道你要使用的类型,那么工厂函数会自动帮你去做对应的事情
简单模式的优点
- 简单讲就是使用简单工厂模式,那么你就不需要关心它的具体实现,
你只需要知道你要使用的类型,那么工厂函数会自动帮你去做对应的事情。 - 简单工厂模式最大的优点在于实现对象的创建和对象的使用分离,将对象的创建交给专门的工厂类负责
简单模式的缺点
- 由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响
- 使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。
- 工厂类不够灵活,增加新的具体产品需要修改工厂类的判断逻辑代码,而且产品较多时,工厂方法代码将会非常复杂。
2.工厂方法模式
工厂方法模式:又称为工厂模式,也叫虚拟构造器模式或者多态工厂模式
它属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对
象的公共接口,而工厂子类则负责生成具体的产品对象,
这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,
即通过工厂子类来确定究竟应该实例化哪一个具体产品类
let UserFactory = function(role) {
if(this instanceof UserFactory) {
var s = new this[role]();
return s;
} else {
return new UserFactory(role);
}
}
//工厂方法函数的原型中设置所有对象的构造函数
UserFactory.prototype = {
SuperAdmin: function() {
this.name = "超级管理员",
this.viewPage = ['首页', '通讯录', '发现页', '应用数据', '权限管理']
},
Admin: function() {
this.name = "管理员",
this.viewPage = ['首页', '通讯录', '发现页', '应用数据']
},
NormalUser: function() {
this.name = '普通用户',
this.viewPage = ['首页', '通讯录', '发现页']
}
}
//调用
let superAdmin = UserFactory('SuperAdmin');
let admin = UserFactory('Admin')
let normalUser = UserFactory('NormalUser')
工厂方法模式的优点
- 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。
- 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,是因为所有的具体工厂类都具有同一抽象父类。
- 使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。
工厂方法模式的缺点
- 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
- 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度
3.抽象工厂模式
抽象工厂其实是一个实现子类继承父类的方法,在这个方法种我我们需要传入子类以及要继承父类的名称.
过渡类的原型继承,不是继承父类的原型,而是通过new 复制一个父类的实例,过渡类不仅仅继承了父类的原型方法,还继承了父类的对象属性.
使用方法
let AccountAbstractFactory = function(subType, superType) {
//判断抽象工厂中是否有该抽象类
if(typeof AccountAbstractFactory[superType] === 'function') {
//缓存类
function F() {};
//继承父类属性和方法
F.prototype = new AccountAbstractFactory[superType] ();
//将子类的constructor指向子类
subType.constructor = subType;
//子类原型继承父类
subType.prototype = new F();
} else {
throw new Error('抽象类不存在!')
}
}
//微信用户抽象类
AccountAbstractFactory.WechatUser = function() {
this.type = 'wechat';
}
AccountAbstractFactory.WechatUser.prototype = {
getName: function() {
return new Error('抽象方法不能调用');
}
}
//普通微信用户子类
function UserOfWechat(name) {
this.name = name;
this.viewPage = ['首页', '通讯录', '发现页']
}
//抽象工厂实现WechatUser类的继承
AccountAbstractFactory(UserOfWechat, 'WechatUser');
//子类中重写抽象方法
UserOfWechat.prototype.getName = function() {
return this.name;
}
//实例化微信用户
let wechatUserA = new UserOfWechat('微信小李');
console.log(wechatUserA.getName(), wechatUserA.type); //微信小李 wechat
let wechatUserB = new UserOfWechat('微信小王');
console.log(wechatUserB.getName(), wechatUserB.type); //微信小王 wechat