JavaScript 三種工廠模式:簡單工廠模式、工廠方法模式、抽象工廠模式。 ...
標簽(空格分隔): JavaScript
- 簡單工廠模式是工廠函數返回實例化對象或者對象,工廠函數作為一個方法。
- 工廠方法模式是工廠函數不作改變,將子類放在工廠原型中;工廠函數返回對應的實例化對象:
return new this[type]();
。不同於簡單工廠,工廠函數需要實例化使用。- 抽象工廠模式是工廠函數直接返回抽象類,那麼這個類就不能實例化使用,需要做出對應的提示比如"抽象方法不能調用",抽象類的方法必須要通過子類重寫。抽象工廠函數作為一個方法不需要實例化,通過點語法在抽象工廠上添加屬性。
1. 簡單工廠模式
簡單工廠模式(Simple Factory),也叫靜態工廠方法,由一個工廠對象決定創建某一種產品對象類的實例。主要用來創建同一類對象。
var Opera = function () {
this.description = '歌劇很好聽~';
}
Opera.prototype.getDesc = function () {
console.info('你造嗎, ' + this.description);
}
var Dance = function () {
this.description = '舞蹈很好看~';
}
Dance.prototype.getDesc = function () {
console.info('你造嗎, ' + this.description);
}
var Crosstalk = function () {
this.description = '相聲很有趣~';
}
Crosstalk.prototype.getDesc = function () {
console.info('你造嗎, ' + this.description);
}
var ArtFactory = function (name) {
var art = null;
switch (name) {
case 'Opera':
art = new Opera();
break;
case 'Dance':
art = new Dance();
break;
case 'Crosstalk':
art = new Crosstalk();
break;
}
return art;
}
// 簡單工廠應用
var dance = ArtFactory('Dance');
console.log(dance);
console.log(dance.description);
dance.getDesc();
// Result
// Dance {description: "舞蹈很好看~"}
// 舞蹈很好看~
// 你造嗎, 舞蹈很好看~
簡單工廠模式的理念就是創建對象;當子類有相同的地方可以抽象提取出來共用,可以簡單創建一個對象,然後通過這個對象大量拓展方法和屬性,併在最終將對象返回出來。
function createBook(name, time, type) {
var obj = new Object();
obj.name = name;
obj.time = time;
obj.type = type;
obj.getName = function () {
console.info(this.name);
}
switch (type) {
case 'js':
obj.description = 'JavaScript是世界上最好的語言!';
obj.getName = function () {
console.info('呵呵,' + this.name + '才是世界上最好的語言!');
}
break;
case 'php':
obj.description = 'PHP是世界上最好的語言!';
break;
case 'c#':
obj.description = 'c#是世界上最好的語言!';
break;
case 'java':
obj.description = 'Java是世界上最好的語言!';
break;
default:
obj.description = 'Python是世界上最好的語言!';
break;
}
return obj;
}
var book = createBook('JavaScript', '2017-01-01', 'js');
console.log(book);
console.log(book.description);
book.getName();
// Result
// {name: "JavaScript", time: "2017-01-01", type: "js", getName: ƒ, description: "JavaScript是世界上最好的語言!"}
// JavaScript是世界上最好的語言!
// 呵呵,JavaScript才是世界上最好的語言!
2. 工廠方法模式
工廠方法模式(Factory Method),將實際創建對象工作推遲到子類當中,即將創建對象的基類放在工廠方法類的原型中,這樣核心類就成了抽象類(非嚴格意義上的)。
// 工廠方法模式
var Factory = function (type, content) {
if (this instanceof Factory) {
var ad = new this[type](content);
return ad;
} else {
return new Factory(type, content);
}
}
Factory.prototype = {
Java: function (content) {
console.info('Java, ' + content);
},
FrontEnd: function (content) {
console.info('前端, ' + content);
},
PHP: function (content) {
console.info('PHP, ' + content);
},
UI: function (content) {
console.info('UI, ' + content);
}
}
// 工廠方法模式應用
var datas = [
{ type: 'Java', content: '只要學好了Java,走遍天下都不怕!' },
{ type: 'FrontEnd', content: '月薪20k!' },
{ type: 'PHP', content: '世界上最好的語言!' },
{ type: 'UI', content: '我想要一種五彩斑斕的黑色!' }
];
datas.forEach(function (data, idnex) {
var ad = new Factory(data.type, data.content);
});
// Result
// Java, 只要學好了Java,走遍天下都不怕!
// 前端, 月薪20k!
// PHP, 世界上最好的語言!
// UI, 我想要一種五彩斑斕的黑色!
3. 抽象工廠模式
抽象工廠模式(Abstract Factory),通過對類的工廠抽象,使其業務用於對產品類簇的創建,而不負責某一具體類產品的實例。
抽象類(abstract)是一種聲明但不能使用的類,當使用時會拋出錯誤;在js中需要手動拋出錯誤提示。
因為抽象工廠是個方法不需要實例化對象,故只需要一份,因此直接為抽象工廠添加類的屬性即可。
抽象工廠其實是一個實現子類繼承父類的方法。
// 抽象工廠方法
var VehicleFactory = function (subType, superType) {
// 判斷抽象工廠中是否有該抽象類
if (typeof VehicleFactory[superType] === 'function') {
// 緩存類
var F = function () {}
// 繼承父類屬性和方法
F.prototype = new VehicleFactory[superType]();
// 將子類constructor指向子類
subType.constructor = subType;
// 子類原型繼承父類
subType.prototype = new F();
subType.uber = superType.prototype;
} else {
throw new Error('未創建該抽象類!');
}
}
// 抽象父類 - 1
VehicleFactory.Car = function () {
this.type = 'car';
}
VehicleFactory.Car.prototype = {
getPrice: function () {
return new Error('抽象方法不能調用!');
},
getSpeed: function () {
return new Error('抽象方法不能調用!');
}
}
// 抽象父類 - 2
VehicleFactory.Truck = function () {
this.type = 'truck';
}
VehicleFactory.Truck.prototype = {
getPrice: function () {
return new Error('抽象方法不能調用!');
},
getSpeed: function () {
return new Error('抽象方法不能調用!');
}
}
// 子類 - 1
var BMW = function (price, speed) {
this.price = price;
this.speed = speed;
}
// 抽象工廠實現對 Car 抽象類的繼承
VehicleFactory(BMW, 'Car');
// 必須在抽象實現後重寫
BMW.prototype.getPrice = function () {
console.info('$' + this.price);
}
BMW.prototype.getSpeed = function () {
console.info(this.speed + 'km/h');
}
// 子類 - 2
var Lamborghini = function (price, speed) {
this.price = price;
this.speed = speed;
}
VehicleFactory(Lamborghini, 'Car');
Lamborghini.prototype = {
getPrice: function () {
console.info('$' + this.price);
},
getSpeed: function () {
console.info(this.speed + 'km/h');
},
getNumber: function () {
console.info('888');
}
}
// 抽象工廠模式應用
var car = new BMW('1,000,000', '500');
console.log(car);
console.log(car.price);
car.getPrice();
car.getSpeed();
// Result
// BMW {price: "1,000,000", speed: "500"}
// 1,000,000
// $1,000,000
// 500km/h
var car_2 = new Lamborghini('2,000,000', '600');
console.log(car_2);
car_2.getPrice();
car_2.getSpeed();
car_2.getNumber();
// Result
// Lamborghini {price: "2,000,000", speed: "600"}
// $2,000,000
// 600km/h
// 888