1、简易工厂模式
简易工厂模式又叫静态工厂方法,由一个工厂对象来决定创建某一类产品对象类的实例,主要用于创建同一类对象 《JavaScript设计模式 张容铭》
1-1、如果类太多,尽量提供一个
下面定义各种汽车类
function Car(color) {
this.color = color
this.type = 'car'
}
Car.prototype = {
//car类身上的方法
}
function Truck(color) {
this.color = color
this.info = '这是卡车的类'
}
Truck.prototype = {
//Truck类上的方法。
}
此时使用时想要生成不同的汽车时,就需要去找到不同的类进行 new 的操作。上面只是两个不同类, 如果我们需要有很多种类型,则会出现一个很明显的问题,全局中暴露出过多的函数,在一些大型项目中增加了命名冲突的可能性,同时每次创建不同的汽车时都需要去找到生成对应汽车的类。因此可以进行处理如下。
function Vehicle(type,color) {
function Car(color) {
this.color = color
this.type = 'car'
}
Car.prototype = {
//car类身上的方法
}
function Truck(color) {
this.color = color
this.info = '这是卡车的类'
}
Truck.prototype = {
//Truck类上的方法。
}
switch(type){
case 'Car':return new Car(color);
case 'Truck':return new Truck(color);
default:throw new Error(`还没有创建${type},先去创建一个吧`)
}
}
此时避免了全局变量过多的危害,同时我们不需要去过多的关注每一个类,只需要传入不同的type,Vehicle就会帮我们返回对应类的实例化对象。同时,对于没有的类型抛出错误。有一个友好的提示。
1-2、一个对象也可以代替多个类
function Vehicle(type,color) {
var o = new Object()
o.color = color
if(type==='Car'){
o.type = 'Car'
o['方法名'] = function(){
//Car 的方法
}
}
if(type==='Truck'){
this.info = '这是卡车的类'
o['方法名'] = function(){
//Truck的方法
}
}
return o
}
1-1和1-2的区别 第一种是通过对不同的类的实例化对象创建,第二种是通过创建一个新对象,然后包装增强其属性和功能来实现,第一种方法如果调用的这些类是继承同一父类,那么他们父类原型上的方法是可以公用的,但是通过第二种方法,每次创建都是一个新的对象,他们的方法不能共用
2、工厂方法模式
通过对产品的抽象使其创建业务主要负责用于创建多类产品的实例
如根据不同的语言生成不同背景和字体颜色的需求处理
function JobFactory(type, content) {
function Java(content) {
this.content = content
(function(content) {
var dev = document.createElement('div')
div.innerHTML = content
div.style.color = 'red'
document.getElementById('container').appendChild(div)
})(content)
}
function Php(content) {
this.content = content
(function(content) {
var div = document.createElement('div')
div.innerHTML = content
div.style.color = 'red'
div.style.background = '#EEE'
})(content)
}
function JavaScript(content) {
this.content = content
(function(content) {
var div = document.createElement('div')
div.innerHTML = content
div.style.color = '#fff'
div.style.background = '#000'
})(content)
}
switch (type) {
case 'Java':
return new Java(content);
case 'Php':
return new Php(content);
case 'JavaScript':
return new JavaScript(content);
default:throw new Error(`还没有创建${type},先去创建一个吧`)
}
}
对于上面的方法,每次新添加一个类时,不仅需要添加一个类,同时还要在switch中添加case判断。因此我们可以看一下安全的工厂方法模式,如下:
var Factory = function(type, content) {
if (this instanceof Factory) {
var s = new this[type](content)
return s
} else {
return new Factory(type, content)
}
}
//工厂原型中设置创建所有类型数据对象的基类
Factory.prototype = {
Java: function() {
//
},
Php: function() {
//
},
JavaScript: function() {
//
}
}
使用时只需要定义好数据
var data = [
{ type: 'Java', content: 'Java后端最好用的语言' },
{ type: 'Php', content: '世界上最好的语言' },
{ type: 'JavaScript', content: '前端语言' },
]
for (var i = 2; i >= 0; i--) {
Factory(data[i].type, data[i].content)
}
3、抽象工厂模式
抽象工厂模式:通过对类的工厂抽象化使其业务用于产品类簇的创建,而不负责创建某一类产品的实例
//抽象工厂模式
var VehicleFactory = function(subType, superType) {
//判断抽象工厂中时候有该抽象类
if (typeof VehicleFactory[superType] === 'function') {
//缓存类
function F() {}
//继承父类属性和方法
F.prototype = new VehicleFactory[superType]()
//将子类的constructor指向子类
subType.constructor = subType
//子类原型继承父类
subType.prototype = new F()
} else {
throw new Error('未创建该抽象类')
}
}
//小汽车抽象类
VehicleFactory.Car = function() {
this.type = 'car'
}
VehicleFactory.Car.prototype = {
getPrice: function() {
return new Error('抽象方法不能调用')
},
getSpeed: function() {
return new Error('抽象方法不能调用')
}
}
//公交车抽象
VehicleFactory.Bus = function() {
this.type = 'bus'
}
VehicleFactory.Bus.prototype = {
getPrice: function() {
return new Error('抽象方法不能调用')
},
getSpeed: function() {
return new Error('抽象方法不能调用')
}
}
//货车抽象类
VehicleFactory.Truck = function(){
this.type = 'truck'
}
VehicleFactory.Truck.prototype = {
getPrice:function(){
return new Error('抽象方法不能调用')
},
getSpeed:function(){
return new Error('抽象方法不能调用')
}
}
使用如下,通过抽象工厂函数,我们能够知道每一个子类属于哪一个类别,同时他们也具备了该类别所必备的属性和方法。由于js不支持抽象化创建和虚拟方法。所以这种模式使用不广泛。
var BMW = function(price,speed){
this.price = price
this.speed = speed
}
VehicleFactory(BMW,'Car')
BMW.prototype.getPrice = function(){
return this.price
}
BMW.prototype.getSpeed = function(){
return this.speed
}
console.log(new BMW('bmw',100))
5、参考资料
《JavaScript设计模式 张容铭》
《JavaScript设计模式 》Addy Osmani著 徐涛译版
6、结束语
最近在看有关js设计模式的知识,整理出来作为笔记,如果错误,欢迎大家指正,谢谢🙏