js設計模式(下)

引用:(23條消息) 《Javascript設計模式與開發實踐》關於設計模式典型代碼的整理(下):模板方法模式、享元模式、職責鏈模式、中介者模式、裝飾模式、狀態模式、適配器模式_QQsilhonette的博客-CSDN博客

8、模板方法模式:一種基於繼承的設計模式。

// 模板方法模式
var Beverage = function (param) {

var boilWater = function () {
console.log('把水煮沸');
};

var brew = param.brew || function () {
throw new Error('必須傳遞brew方法');
};

var pourInCup = param.pourInCup || function () {
throw new Error( '必須傳遞 pourInCup 方法' );
};
var addCondiments = param.addCondiments || function () {
throw new Error( '必須傳遞 addCondiments 方法' );
};

var F = function(){};
F.prototype.init = function(){ boilWater();
brew();
pourInCup();
addCondiments();
};
return F;
};

var Coffee = Beverage({ brew: function(){
console.log( '用沸水沖泡咖啡' ); },
pourInCup: function(){
console.log( '把咖啡倒進杯子' );
},
addCondiments: function(){
console.log( '加糖和牛奶' ); }
});

var Tea = Beverage({
brew: function(){
console.log( '用沸水浸泡茶葉' ); },
pourInCup: function(){
console.log( '把茶倒進杯子' );
},
addCondiments: function(){
console.log( '加檸檬' );
}
});
// 測試
var coffee = new Coffee();
coffee.init();

var tea = new Tea();
tea.init();
9、享元模式:運用共享技術來有效支持大量細粒度的對象。

內部狀態與外部狀態:
 內部狀態存儲於對象內部。
 內部狀態可以被一些對象共享。
 內部狀態獨立於具體的場景,通常不會改變。
 外部狀態取決於具體的場景,並根據場景而變化,外部狀態不能被共享。

// 享元模式
var Model = function (sex) {
this.sex = sex; // 性別爲內部狀態
};

Model.prototype.takePhoto = function () {
console.log('sex=' + this.sex + ' underwear=' + this.underwear); // 內衣爲外部狀態
};
// 測試
var maleModel = new Model('male');
femaleModel = new Model('female');

for (var i = 1; i <= 50; i++) {
maleModel.underwear = 'underwear' + i;
maleModel.takePhoto();
};

for ( var j = 1; j <= 50; j++ ){
femaleModel.underwear = 'underwear' + j;
femaleModel.takePhoto();
};

10、職責鏈模式:使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關係,將這些對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有一個對象處理它爲止。


// 職責鏈模式
var order500 = function( orderType, pay, stock ){
if ( orderType === 1 && pay === true ){
console.log( '500 元定金預購,得到 100 優惠券' );
}else{
return 'nextSuccessor'; // 我不知道下一個節點是誰,反正把請求往後面傳遞
}
};

var order200 = function( orderType, pay, stock ){
if ( orderType === 2 && pay === true ){
console.log( '200 元定金預購,得到 50 優惠券' );
}else{
return 'nextSuccessor'; // 我不知道下一個節點是誰,反正把請求往後面傳遞
}
};

var orderNormal = function( orderType, pay, stock ){
if ( stock > 0 ){
console.log( '普通購買,無優惠券' );
}else{
console.log( '手機庫存不足' );
}
};
// Chain.prototype.setNextSuccessor 指定在鏈中的下一個節點
// Chain.prototype.passRequest 傳遞請求給某個節點
var Chain = function (fn) {
this.fn = fn;
this.successor = null;
};

Chain.prototype.setNextSuccessor = function (successor) {
return this.successor = successor;
};

Chain.prototype.passRequest = function () {
var ret = this.fn.apply(this, arguments);

if(ret === 'nextSuccessor') {
return this.successor && this.successor.passRequest.apply(this.successor, arguments);
}

return ret;
};
// 測試
var chainOrder500 = new Chain( order500 );
var chainOrder200 = new Chain( order200 );
var chainOrderNormal = new Chain( orderNormal );

chainOrder500.setNextSuccessor( chainOrder200 );
chainOrder200.setNextSuccessor( chainOrderNormal);

chainOrder500.passRequest( 1, true, 500 );
chainOrder500.passRequest( 2, true, 500 );
chainOrder500.passRequest( 3, true, 500 );
chainOrder500.passRequest( 1, false, 0 );

11、中介者模式:增加一箇中介者對象後,所有的相關對象都通過中介者對象來通信,而不是互相引用,所以當一個對象發生改變時,只需要通知中介者對象即可。

// 中介者模式
var goods = { // 手機庫存
"red|32G": 3,
"red|16G": 0,
"blue|32G": 1,
"blue|16G": 6
};

var mediator = (function(){
var colorSelect = document.getElementById( 'colorSelect' ),
memorySelect = document.getElementById( 'memorySelect' ),
numberInput = document.getElementById( 'numberInput' ),
colorInfo = document.getElementById( 'colorInfo' ),
memoryInfo = document.getElementById( 'memoryInfo' ),
numberInfo = document.getElementById( 'numberInfo' ),
nextBtn = document.getElementById( 'nextBtn' );
return {
changed: function( obj ){
var color = colorSelect.value, // 顏色
memory = memorySelect.value,// 內存
number = numberInput.value, // 數量
stock = goods[ color + '|' + memory ]; // 顏色和內存對應的手機庫存數量
if ( obj === colorSelect ){ // 如果改變的是選擇顏色下拉框
colorInfo.innerHTML = color;
}else if ( obj === memorySelect ){
memoryInfo.innerHTML = memory;
}else if ( obj === numberInput ){
numberInfo.innerHTML = number;
}
if ( !color ){
nextBtn.disabled = true; nextBtn.innerHTML = '請選擇手機顏色'; return;
}
if ( !memory ){
nextBtn.disabled = true; nextBtn.innerHTML = '請選擇內存大小'; return;
}
if ( ( ( number - 0 ) | 0 ) !== number - 0 ){ // 輸入購買數量是否爲正整數
nextBtn.disabled = true;
nextBtn.innerHTML = '請輸入正確的購買數量'; return;
}
nextBtn.disabled = false;
nextBtn.innerHTML = '放入購物車';
}
}
})();

// 事件函數:
colorSelect.onchange = function(){
mediator.changed( this );
};
memorySelect.onchange = function(){
mediator.changed( this );
};
numberInput.oninput = function(){
mediator.changed( this );
};

12、裝飾者模式:在不改變對象自身的基礎上,在程序運行期間給對象動態地添加職責。

裝飾者模式和代理模式:裝飾者模式是實實在在的爲對象增加新的職責和行爲,而代理做的事情還是跟本體 一樣。
// 用AOP裝飾模式
Function.prototype.before = function(beforefn) {
var _self = this; // 保存原函數的引用
return function () {
beforefn.apply(this, arguments);
return _self.apply(this, arguments);
}
}

Function.prototype.after = function (afterfn) {
var _self = this;
return function () {
var ret = _self.apply(this, arguments);
afterfn.apply(this, arguments);
return ret;
}
}

13、狀態模式:允許一個對象在其內部狀態改變時改變它的行爲,對象看起來似乎修改了它的類。

// 狀態模式
var delegate = function (client, delegation) {
return {
buttonWasPressed: function () {
return delegation.buttonWasPressed.apply(client, arguments);
}
}
};

var FSM = {
off: {
buttonWasPressed: function() {
console.log('關燈');
this.button.innerHTML = '下一次按我是開燈';
this.currState = this.onState;
}
},
on: {
buttonWasPressed: function(){
console.log( '開燈' );
this.button.innerHTML = '下一次按我是關燈';
this.currState = this.offState;
}
}
};

var Light = function () {
this.offState = delegate(this, FSM.off);
this.onState = delegate(this, FSM.on);
this.currState = this.offState;
this.button = null;
};

Light.prototype.init = function () {
var button = document.createElement('button');
self = this;
button.innerHTML = '已關燈';
this.button = document.body.appendChild(button);
this.button.onclick = function () {
self.currState.buttonWasPressed();
}
};
// 測試
var light = new Light();
light.init();

14、適配器模式:解決兩個軟件實體間的接口不兼容的問題。

// 適配器模式
var renderMap = function( map ){
if ( map.show instanceof Function ){
map.show();
}
};

var googleMap = {
show: function(){
console.log( '開始渲染谷歌地圖' );
}
};
var baiduMap = {
display: function(){
console.log( '開始渲染百度地圖' );
}
};
var baiduMapAdapter = {
show: function(){
return baiduMap.display();
}
};
renderMap( googleMap ); // 輸出:開始渲染谷歌地圖
renderMap( baiduMapAdapter ); // 輸出:開始渲染百度地圖

 

 

 


QQsilhonette
關注
————————————————
版權聲明:本文爲CSDN博主「QQsilhonette」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/QQsilhonette/article/details/84954376

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章