乙個根據等級計算獎金的例子。
var stratagies = ,
"a": function (salary) ,
"b": function (salary)
};var calculatebonus = function (level, salary) ;
console.log(calculatebonus('s', 20000));
console.log(calculatebonus('a', 10000));
所有跟計算獎金有關的邏輯不再放在context中,而是分布在各個策略物件中。context並沒有計算將近的能力,而是把這個職責委託給了某個策略物件。每個策略物件負責的演算法已被封裝在物件內部。當我們對這些策略物件發出「計算獎金」的請求時,他們會返回各自不同的計算結果,這正是物件多型性的體現。
使用策略模式實現緩動動畫
思路和一些準備工作:
我們目標編寫乙個動畫類和一些緩動演算法,讓小球以各種各樣的緩動效果在頁面中運動。
在運動之前,需要記錄一些有用的資訊,至少包括:動畫開始時,小球所在的原始位置;小球移動的目標位置;動畫開始時的準確時間點;運動持續的時間。
隨後,我們會用setinterval建立乙個定時器。在定時器的每一幀裡,我們會把動畫已消耗的時間、小球的原始位置、目標位置和動畫持續的總時間等資訊傳入緩動演算法。該演算法會通過這幾個引數,計算出小球當前應該所在的位置。最後再更新該div對應的css屬性,小球就能順利的運動起來了。
讓小球運動起來:
在實現完整的功能前,我們先了解一些常見的緩動演算法。這些演算法都接受4個引數,這4個引數的含義分別是動畫已消耗的時間、原始位置、目標位置、動畫持續的總時間,返回的值則是動畫元素應該處在的當前位置。
var tween = ,
easein: function (t, b, c, d) ,
strongeasein: function (t, b, c, d) ,
strongeaseout: function (t, b, c, d) ,
sineasein: function (t, b, c, d) ,
sineaseout: function (t, b, c, d)
};
現在我們開始編寫完整的**,下面**的思想來自jq庫,由於目的是演示策略模式,而非編寫乙個完整的動畫庫,因此省去了動畫佇列控制等更多完整功能。
首先在頁面中放置乙個div:
我是div
接下來定義animate類,animate的建構函式接受乙個引數:即將運動起來的dom節點。
var animate = function (dom) ;
接下來animate.prototype.start方法負責啟動這個動畫,在動畫被啟動的瞬間,要記錄一些資訊,供快取演算法在以後計算小球當前位置時使用。在記錄完這些資訊後,此方法還要負責啟動定時器。
animate.prototype.start = function (propertyname, endpos, duration, easing)
}, 19);
};
再接下來是
animate.prototype.step方法,該方法代表小球運動的每一幀要做的事情。在此處,這個方法負責計算小球的當前位置和呼叫更新css屬性值的方法animate.prototype.update.
animate.prototype.step = function ()
var pos = this.easing(t-this.starttime, this.startpos, this.endpos-this.startpos, this.duration); //pos為小球當前位置
this.update(pos); // 更新小球的css屬性
};
最後是負責更新小球的css屬性值的
animate.prototype.update方法:
animate.prototype.update = function (pos)
進行測試:
var div = document.getelementbyid('div');
var animate = new animate(div);
animate.start('left', 500, 1000, 'strongeaseout');
'top', 1500, 500, 'strongeasein');
通過這段**,可以看到小球按照我們的期望以各種各樣的緩動演算法在頁面中運動。我們使用策略模式把演算法傳入動畫類,來達到各種不同的緩動效果,這些演算法都可以輕易被替換為另乙個演算法,這是策略模式的經典應用之一。
從定義上看,策咯模式就是用來封裝演算法的。在實際開發中,我們通常會把演算法的含義擴散開來,使策略模式也可以用來封裝一系列的「業務規則」。只要這些業務規則指向的目標一致,並且可以被替換使用,我們就可以用可以用策略模式來封裝它們。
表單驗證
假設我們要編寫乙個註冊的頁面,有如下幾條校驗邏輯。
1.使用者名稱不能為空
2.密碼長度不能少於6位
3.手機號碼必須符合格式
表單校驗的第乙個版本:
此處沒有引入策略模式。
這是一種很常見的編碼方式,缺點如下:
1.registerform.onsubmit函式比較龐大,包含了很多分支語句,這些語句需要覆蓋所有的校驗規則
2.registerform.onsubmit缺乏彈性
3.演算法的復用性差
用策略模式重構表單校驗
下面用策略模式來重構表單校驗的**,很顯然第一步要把這些校驗邏輯都封裝成策略物件:
var strategies =
},minlength: function (value, length, errormsg)
},ismobile: function (value, errormsg) $)/.test(value) )
}};
接下來準備實現validator類。validator類在這裡作為context,負責接收使用者的請求並委託給strategy物件。在給出
validator類的**之前,有必要提前了解使用者是如何向v
alidator類傳送請求的,這有助於我們知道如何去編寫v
alidator類的**。**如下
var validatafunc = function () ;
var registerform = document.getelementbyid('registerform');
registerform.onsubmit = function ()
};
最後是validator類的實現:
var validator = function () ;
validator.prototype.add = function (dom, rule, errormsg) );
};validator.prototype.start = function ()
}};
使用策略模式重構**後,我們僅僅通過「配置」的方式就可以完成乙個表單的校驗,這些校驗規則也可以復用在程式的任何地方,還能作為外掛程式的形式,方便的被移植到其他專案中。
在某個文字輸入框新增多種校驗規則
目前的表單校驗實現留有一點小遺憾:乙個文字輸入框只能對應一種檢驗規則,如果我們既想校驗它是否為空,又想校驗它輸入文字的長度不小於10呢?我們期望以這樣的方式進行校驗:
validator.add(registerform.username, [,]);
下面提供的**可用於乙個文字輸入框對應多種檢驗規則:
JS 設計模式 策略模式
策略模式指的是定義一系列的演算法,把它們乙個個封裝起來。將不變的部分和變化的部分隔開是每個設計模式的主題,策略模式也不例外,策略模式的目的就是將演算法的使用與演算法的實現分離開來。可以很好的替換if else混亂的 var strategies a function salary b functio...
js 設計模式 策略模式
定義 將定義的一組演算法封裝起來,使其相互之間可以替換。封裝的演算法具有一定的獨立性,不會隨客戶端的變化而變化 廢話不多說,先來個例子 例如要寫乙個計算兩個數加減乘除的方法,會有人這麼寫 countnum type,num1,num2 else if type subtract else if ty...
js設計模式 策略模式
策略模式的定義是 定義一系列的演算法,把它們乙個個封裝起來,並且使它們可以相互替換。策略模式指的是定義一系列的演算法,把它們乙個個封裝起來。將不變的部分和變化的部分隔開是每個設計模式的主題,策略模式也不例外,策略模式的目的就是將演算法的使用與演算法的實現分離開來。乙個基於策略模式的程式至少由兩部分組...