本文共--字 阅读约--分钟 | 浏览: -- Last Updated: 2021-12-15
简单工厂模式(Simple Factory):又叫静态工厂方法,由一个工厂对象决定创建某一种产品对象类的实例。主要用于创建同一类对象。
通过封装一个函数创建需要的对象,而不需要关注这些对象到底依赖于哪个基类,使用者只需要这个函数就可以了,这个函数通常也被称为工厂函数,这种模式叫简单工厂模式。
var BasketBall = function() {
this.intro = "篮球盛行于美国";
}
BasketBall.prototype = {
getMember() {
console.log("每个队伍需要5名队员");
},
}
var FootBall = function() {
this.intro = "足球在世界范围内流行";
}
FootBall.prototype = {
getMember() {
console.log("每个队伍需要11名队员");
},
}
var SportsFactory = function (name) {
switch(name) {
case 'basketball':
return new BasketBall();
case 'football':
return new FootBall();
}
}
上面示例是对不同的类实例化,不过除此之外,简单工厂模式还可以用来创建相似对象,所以在一些场景下,我们可以利用这种模式将相似的东西提取,不相似的针对处理即可,又由于这里没有父类,也就无需任何继承,只需要简单创建一个对象即可,然后通过这个对象拓展方法和属性,并将最终的对象返回出来。
function createBall(name, member, intro) {
var o = new Object();
o.name = name;
o.intro = intro;
o.member = member;
o.getMember = function() {
console.log(`每个队伍需要${o.member}名队员`)
}
return o;
}
var football = createBall("football", 11, "足球在世界范围内流行")
总结:第一种是通过类实例化对象创建的,第二种是通过创建一个新对象然后包装增强其属性和功能来实现的。他们之间的差异是,通过类创建的对象,如果这些类继承同一父类,那么它们的父类原型上的方法是可以共用的,后面寄生方式创建的对象都是一个新的个体,所以他们的方法就不能共用了,当然如何选择,需要根据场景来决定。
工厂方法模式(Factory Method):通过对产品类的抽象使其创建业务,主要负责用于创建多类产品的实例。
工厂方法模式本意是说将实际创建对象工作推迟到子类当中,这样核心类就成了抽象类,所以我们可以将工厂方法看作是一个实例化对象的工厂类,而我们创建对象的基类放在工厂方法类的原型中即可。
var Java =function(content) {
this.content = content;
(function(content) {
var div = document.createElement('div');
div.innerHTML = content;
div.style.color = 'green';
document.getElementById('container').appendChild(div);
})(content)
}
var JavaScript =function(content) {
this.content = content;
(function(content) {
var div = document.createElement('div');
div.innerHTML = content;
div.style.color = 'yellow';
div.style.background = 'red';
document.getElementById('container').appendChild(div);
})(content)
}
// 工厂方法类
var ProgramFactory = function(type, content) {
if (this instanceof Factory) {
return new this[type](content)
}
return new Factory(type, content);
}
ProgramFactory.prototype = {
Java, // 创建对象的基类
JavaScript
}
上面这种场景,有多种程序类(Java/JavaScript/…),并且其在页面都要不同的展示,如果使用简单工厂模式,则工厂类就会过于臃肿,因为简单工厂模式只有一个工厂类,它需要处理所有的创建逻辑,如果程序类超过多种,那么整个switch
语句将不断增加。
这时候就需要工厂方法模式来处理,核心的工厂类不再负责所有的对象的创建,而是将创建的工作交给子类去做,这个核心类就变了一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口(比如此例中的content属性),而不接触哪一个类应当被实例化这种细节。
通过调用工厂方法来创建对象,而不是通过调用具体的构造函数。这样,我们以后再添加其他类的时候,只需在ProgramFactory这个工厂类的原型里面添加就可以了,这样就可以将“一批”类通过一个工厂方法“管理”起来(共性),也能保证各个类有自己的不同实现(个性)。
抽象工厂模式(Abstract Factory):通过对类的工厂抽象使其业务用于产品类簇的创建,而不负责创建某一类产品的实例。
抽象类是一种声明但不能使用的类,当你使用时会报错,其具体实现要求各个子类去实现,我们可以在JavaScript中模拟抽象类。
var Car = function () {};
Car.prototype = {
getPrice() {
return new Error('抽象方法不能调用');
}
}
这个Car
类其实什么都不做,没有任何属性,原型上的方法一旦调用就会报错。但是在继承上却是很有用的,因为定义了一种类,并定义了该类所必备的方法,如果子类中没有重写这些方法,那么当调用时能找到原型中的这些方法就会报错。
在面向对象的编程语言中,这是很有必要的,在一些应用中,总会有一些子类去继承另一些父类,这些父类经常会定义一些必要方法却没有具体的实现,一旦用子类创建了一个对象,该对象总是具备一些必要的方法,但如果这些必要的方法从父类中继承过来而没有具体去重写实现,那么实例化对象便会调用父类中的这些方法,如果父类能有一个友好的提示,那么对于忘记重写子类的这些错误的避免是很有帮助的。这也是抽象类的一个作用,即定义一个产品簇,并声明一些必备的方法,如果子类中没有重写就会抛出错误。
之前提到的简单工厂模式和工厂方法模式都是用来创建实例化对象的,而抽象工厂模式却不用来创建对象,抽象类中定义的方法只是显性地定义一些功能,但没有具体的实现,而一个对象是要具有一套完整的功能的,所以用抽象类创建的对象当然也是“抽象的”,所以不能使用它来创建一个真实的对象。
var VehicleFactory = function(subType, superType) {
// 判断抽象工厂中是否有该抽象类
if (typeof VehicleFactory[superType] === 'function') {
function F() {};
F.prototype = new VehicleFactory[superType]();
subType.constructor = subType;
subType.prototype = new F();
} else {
throw new Error('未创建该抽象类')
}
}
// 小汽车抽象类
VehicleFactory.Car = function() {
this.type = 'car';
}
VehicleFactory.Car.prototype = {
getPrice() {
return new Error('抽象方法不能调用')
}
}
// 公交车抽象类
VehicleFactory.Bus = function() {
this.type = 'bus';
}
VehicleFactory.Bus.prototype = {
getSpeed() {
return new Error('抽象方法不能调用')
}
}
// BMW汽车子类
var BMW = function(price) {
this.price = price;
}
// 抽象工厂实现对Car抽象类的集成
VehicleFactory(BMW, 'Car');
BMW.prototype.getPrice = function() {
return this.price;
}
var b1 = new BMW(100);
console.log(b1.getPrice()); // 100
console.log(b1.type) // car
抽象工厂其实是一个实现子类继承父类的方法,需要注意的是,对过度类F的原型继承时,不是继承父类的原型,而是通过new关键字复制的父类的一个实例new VehicleFactory[superType]()
,这么做是因为过度类不仅仅继承父类的原型方法,还要继承父类的对象属性,所以要通过new关键字将父类的构造函数执行一遍来复制构造函数中的属性和方法。
工厂模式最大的特点就是“复制/量产”,统一管理“一批”拥有“相同共性”的产品,但并不插手其各自的“个性”实现。