1.單例模式
定義
一個(gè)類(lèi)只產(chǎn)生唯一的實(shí)例
實(shí)現(xiàn)
-
es5
function Single(name) { this.instance = null; this.name = name; this.init(); } Single.prototype.init = function() { console.log(this.name) } Single.getInstance = function(name) { if (!this.instance) { this.instance = new Single(name); } return this.instance; }; var a = Single.getInstance('test_a') var b = Single.getInstance('test_b') console.log(a,b,a===b)這里會(huì)發(fā)現(xiàn)只打印了一次
this.name,且this.name為test_a,而a和b是兩個(gè)一樣的對(duì)象 -
es6
class Single { constructor(name) { this.instance = null; this.name = name; this.init(); } //保證可以直接引用getInstance方法, static getInstance(name) { if (!this.instance) { this.instance = new Single(name); } return this.instance; } } var a = Single.getInstance('test_a') var b = Single.getInstance('test_b') console.log(a,b,a===b) -
惰性單例
保證在需要的時(shí)候才創(chuàng)建對(duì)象實(shí)例
var single = function (name) { console.log(name) return name }; var getSingle = function (fn) { var result; return function () { return result || (result = fn.apply(this, arguments)) } } var test = getSingle(single) test('test_a'); test('test_b');
??
-
彈框
假設(shè)一個(gè)場(chǎng)景,每次點(diǎn)擊按鈕彈出一個(gè)彈框,要通過(guò)創(chuàng)建一個(gè)
div實(shí)現(xiàn),創(chuàng)建時(shí)不必每次都創(chuàng)建一個(gè)新的div<button id="btn">創(chuàng)建</button> <script> var single = function () { var div = document.createElement("div"); div.style.border = '1px solid #000'; div.style.width = '200px'; div.style.height = '80px'; document.body.appendChild(div); return div; }; var getSingle = function (fn) { var result; return function () { return result || (result = fn.apply(this, arguments)) } } var createSingle = getSingle(single); document.getElementById("btn").onclick = function () { var div = createSingle(); //div.style } </script>
-
驗(yàn)證
一般經(jīng)常寫(xiě)react項(xiàng)目,這中場(chǎng)景很少會(huì)遇到,我在想,做一些信息驗(yàn)證的時(shí)候是不是可以用到這種模式。
假設(shè)我有很多地方有同樣的邏輯,例如驗(yàn)證一部分信息,當(dāng)然可以調(diào)用一個(gè)公共的函數(shù),可是如果是一個(gè)異步的邏輯,用到
Promise,每次都要new Promise,這樣在相同的條件下就可以執(zhí)行一次new Promise就可以了。class Verify { constructor() { this.instance = null; this.conditions = null; } static getInstance(conditions) { // 驗(yàn)證條件 if (this.conditions !== conditions) { this.conditions = conditions; this.instance = new Promise(function (resolve, reject) { //... }) } return this.instance; } } // 其他地方調(diào)用 let promise = Verify.getInstance(/*conditions*/); promise.then((res) => { //... })
2.工廠模式
定義
簡(jiǎn)單工廠:由一個(gè)工廠對(duì)象決定創(chuàng)建某一產(chǎn)品對(duì)象類(lèi)的實(shí)例
工廠方法:對(duì)產(chǎn)品類(lèi)抽象,創(chuàng)建多產(chǎn)品類(lèi)的實(shí)例
抽象工廠:對(duì)類(lèi)的工廠抽象,創(chuàng)建產(chǎn)品類(lèi)簇,不會(huì)創(chuàng)建某一類(lèi)產(chǎn)品實(shí)例
實(shí)現(xiàn)
-
簡(jiǎn)單工廠模式
假如有很多類(lèi)很類(lèi)似,可以分為一類(lèi),我們就可以用簡(jiǎn)單工廠模式解決
var Apple = function() { this.name = 'Apple'; } Apple.prototype = { eat:function() { //... } } var Banana = function() { this.name = 'Banana'; } Banana.prototype = { eat:function() { //... } } //定義一個(gè)水果工廠 var Fruit = function(name) { switch(name){ case 'apple': return new Apple(); case 'banana': return new Banana(); } } //當(dāng)需要某個(gè)具體對(duì)象時(shí),調(diào)用水果工廠就可以 var apple = Fruit('apple') -
工廠方法模式
var Fruit = function(type) { //第一次進(jìn)入時(shí)this是window if(this instanceof Fruit) { var fruit = new this[type](); return fruit; } else { return new Fruit(type); } } //工廠方法函數(shù)的原型中創(chuàng)建對(duì)象 Fruit.prototype = { Apple: function() { this.name = "Apple", this.eat = function() {/* ... */} }, Banana: function() { this.name = "Banana", this.eat = function() {/* ... */} }, } var apple = Fruit('Apple');使用工廠方法模式,產(chǎn)品類(lèi)就變成了抽象類(lèi)。每次創(chuàng)建新的產(chǎn)品類(lèi)只需要修改工廠函數(shù)的原型。
-
抽象工廠模式
所謂抽象,就是父類(lèi)抽象共同方法特性,但是具體實(shí)現(xiàn)由每個(gè)子類(lèi)去實(shí)現(xiàn)該方式。
let Food = function(subType, superType) { //是否存在抽象類(lèi) if(typeof Food[superType] === 'function') { //緩存類(lèi) function F() {}; //繼承父類(lèi)屬性和方法 F.prototype = new Food[superType] (); //將子類(lèi)的constructor指向子類(lèi) subType.constructor = subType; //子類(lèi)原型繼承父類(lèi) subType.prototype = new F(); } else { throw new Error('抽象類(lèi)不存在!') } } Food.Fruit = function() { this.type = 'fruit'; } Food.Fruit.prototype = { eat: function() { return new Error('抽象方法不能調(diào)用'); } } //水果子類(lèi) function Fruit(name) { this.name = name; } //抽象工廠實(shí)現(xiàn)WechatUser類(lèi)的繼承 Food(Fruit, 'Fruit'); //重寫(xiě)抽象方法 Fruit.prototype.eat = function() { //... } let apple = new Fruit('apple'); -
比較
工廠方法是對(duì)簡(jiǎn)單工廠的抽象
抽象工廠是在工廠方法的基礎(chǔ)上進(jìn)一步抽象
??
暫時(shí)想到對(duì)于功能相似組件的封裝,(動(dòng)態(tài)判斷加載不同的組件、樣式,角色權(quán)限,頁(yè)面路由等等)可以用簡(jiǎn)單的工廠模式。一般不會(huì)用到抽象工廠。
3.建造者模式
定義
將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使同樣的構(gòu)建過(guò)程可以創(chuàng)建不同的表示。
實(shí)現(xiàn)
//定義一個(gè)肉類(lèi)
var Meat = function (name) {
this.name = name
}
Meat.prototype.getPrice = function () {
var price = 0;
switch (this.name) {
case 'Chicken':
price = 10;
break;
case 'Pork':
price = 20;
break;
case 'Beef':
price = 30;
break;
default:
break;
}
return price
}
//定義一個(gè)菜類(lèi)
var Vegetables = function (name) {
this.name = name
}
Vegetables.prototype.getPrice = function () {
var _this = this;
var price = 0;
switch (this.name) {
case 'Cabbage':
price = 1;
break;
case 'Carrots':
price = 2;
break;
case 'Potatoes':
price = 3;
break;
default:
break;
}
return price
}
//定義食物類(lèi)
var Food = function(meat,vegetables) {
this.meat = meat
this.vegetables = vegetables
}
Food.prototype.getPrice = function() {
var _this = this;
var meat = new Meat(this.meat)
var vegetables = new Vegetables(this.vegetables)
return meat.getPrice() + vegetables.getPrice()
}
var food = new Food('Pork','Potatoes')
food.getPrice()
主要實(shí)現(xiàn)分布構(gòu)建一個(gè)復(fù)雜的對(duì)象,使各個(gè)部分之間相互解耦
??
實(shí)現(xiàn)一個(gè)復(fù)雜的組件,例如react中拆分組件、實(shí)現(xiàn)笛卡爾積(如上)
不同工種薪資計(jì)算:
var Human = function(name) {
this.name = name;
}
var Work = function(work) {
var _this = this;
(function(){
switch(work){
case 'Primary':
_this.work = 'Primary';
_this.price = 100;
break;
case 'Senior':
_this.work = 'Senior';
_this.price = 150;
break;
default:
_this.price = 0;
break;
}
})(work,_this)
}
Work.prototype.getPrice = function(time) {
return time*this.price
}
var Person = function(name,work) {
this.name = new Human(name);
this.work = new Work(work)
}
var person = new Person('Tom','Senior')
console.log(person.name.name)
console.log(person.work.work)
console.log(person.work.getPrice(10))
4.觀察者模式
定義
觀察者模式又稱(chēng)發(fā)布-訂閱(Publish/Subscribe)模式,定義對(duì)象間的一種一對(duì)多的依賴(lài)關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴(lài)于它的對(duì)象都將得到通知。例如dom事件,也是js和dom之間實(shí)現(xiàn)的一種觀察者模式。
實(shí)現(xiàn)
function Observer() {
//訂閱列表
this.subscribes = {};
}
Observer.prototype = {
//訂閱事件
listen: function(eventType, fn){
var _this = this;
if(!(eventType in _this.subscribes)) {
_this.subscribes[eventType] = [];
}
_this.subscribes[eventType].push(fn);
return this;
},
// 觸發(fā)事件(發(fā)布事件)
publish: function(eventType){
var _this = this;
var fns = Array.prototype.slice.call(arguments,1);
for(var i = 0; i < _this.subscribes[eventType].length; i++) {
_this.subscribes[eventType][i].apply(_this,fns);
}
return this;
},
// 刪除訂閱事件
remove: function(eventType, fn){
var currentEvent = this.subscribes[eventType];
var len = 0;
if (currentEvent) {
len = currentEvent.length;
for (var i = len - 1; i >= 0; i--){
if (currentEvent[i] === fn){
currentEvent.splice(i, 1);
}
}
}
return this;
}
}
//訂閱事件A
var o = new Observer();
o.listen('test', function(data){
console.log(data);
});
var callback = function(data) {
console.log(data)
}
o.listen('test', callback);
o.publish('test', 'first');
o.remove('test', callback);
o.publish('test', 'second');
5.原型模式
定義
原型實(shí)例指向創(chuàng)建對(duì)象的類(lèi),創(chuàng)建新的對(duì)象可以共享原型對(duì)象的屬性和方法
實(shí)現(xiàn)
var Food = function(name) {
this.name = name
}
Food.prototype.eat = function(){
//...
}
var food1 = new Food('food1');
var food2 = new Food('food2');
console.log(food1.eat === food2.eat)//true
//Object.create
var food = {
eat: function () { },
name:''
};
// 使用Object.create創(chuàng)建
var food1 = Object.create(food);
food.name = 'food1'
如果有問(wèn)題,希望指出