策略模式
- 策略模式指的是 定義一系列的算法,把它們一個個封裝起來,將不變的部分和變化的部分隔開,實際就是將算法的使用和實現分離出來, 這樣就能避免不少的if 條件判斷, 而且加強了代碼的複用性;
- 其中包含一個策略類, 和一個環境類;
- 計算獎金的例子:
// 策略類
var performanceS = function () {}
performanceS.prototype.calculate = function (salary) {
return salary * 4;
}
var performanceA = function () {}
performanceA.prototype.calculate = function (salary) {
return salary * 3;
}
var performanceB = function () {
}
performanceB.prototype.calculate = function (salary) {
return salary * 2;
}
// 環境類
var Bonus = function () {
this.salary = null;
this.strategy = null;
}
Bonus.prototype.setSalary = function (salary) {
this.salary = salary;
}
Bonus.prototype.setStrategy = function (strategy) {
this.strategy = strategy;
}
Bonus.prototype.getBonus = function () {
return this.strategy.calculate(this.salary);
}
var bonus = new Bonus();
bonus.setSalary(1000); // 設置原始工資
bonus.setStrategy(new performanceS()); // 設置策略對象
console.log(bonus.getBonus());
// 策略類
var tween = {
/**
* 緩動動畫
* @param t 已消耗的時間
* @param b 小球的原始位置
* @param c 小球的目標位置
* @param d 動畫持續的總時間
* @return {*}
*/
linear: function (t, b, c, d) {
return c * t / d + b;
},
easeIn: function (t, b, c, d) {
return c * (t /= d) * t + b;
},
strongEaseIn: function (t, b, c, d) {
return c * (t /= d) * t * t * t * t + b;
},
strongEaseOut: function (t, b, c, d) {
return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
},
sineaseIn: function (t, b, c, d) {
return c * (t /= d) * t * t + b;
},
sineaseOut: function (t, b, c, d) {
return c * ((t = t / d -1) * t * t + 1) + b;
}
}
// 環境類
var Animate = function (dom) {
this.dom = dom;
this.startTime = 0;
this.startPos = 0;
this.endPos = 0;
this.propertyName = null;
this.easing = null;
this.duration = null;
}
/**
* 啓動動畫
* @param propertyName 屬性
* @param endPose 結束位置
* @param duration 持續時間
* @param easing 緩動算法
*/
Animate.prototype.start = function (propertyName, endPose, duration, easing) {
this.startTime = +new Date();
this.startPos = this.dom.getBoundingClientRect()[propertyName]; // dom 節點初始位置
this.propertyName = propertyName;
this.endPos = endPose;
this.duration = duration;
this.easing = tween[easing];
var self = this;
var timerId = setInterval(function () {
if (self.step() === false) {
clearInterval(timerId);
}
}, 19);
}
// 每 19 毫秒就執行 一次
Animate.prototype.step = function () {
var t = +new Date();
if (t > this.startTime + this.duration) {
this.update(this.endPos);
return false;
}
var pos = this.easing(
t - this.startTime,
this.startPos,
this.endPos - this.startPos,
this.duration
);
this.update(pos);
}
Animate.prototype.update = function (pos) {
this.dom.style[this.propertyName] = pos + 'px';
}
var div = document.getElementById('div');
var animate = new Animate(div);
// animate.start('left', 1500, 5000, 'linear');
// animate.start('left', 1500, 5000, 'easeIn');
// animate.start('left', 1500, 5000, 'strongEaseIn');
animate.start('left', 1500, 5000, 'strongEaseOut');
// animate.start('left', 1500, 5000, 'sineaseIn');
// animate.start('left', 1500, 5000, 'sineaseOut');
// animate.start('top', 1500, 5000, 'linear');
// animate.start('top', 1500, 5000, 'easeIn');
// animate.start('top', 1500, 5000, 'strongEaseIn');
// animate.start('top', 1500, 5000, 'strongEaseOut');
// animate.start('top', 1500, 5000, 'sineaseIn');
// animate.start('top', 1500, 5000, 'sineaseOut');
// 策略類
var strategies = {
isNonEmpty: function (value, errorMsg) {
if (value === '') {
return errorMsg;
}
},
minLength: function (value, length, errorMsg) {
if (value.length < length) {
return errorMsg;
}
},
isMobile: function (value, errorMsg) {
if (!/^1[3|5|8][0-9]{9}$/.test(value)) {
return errorMsg;
}
}
}
// 環境類
var Validator = function () {
this.cache = [];
}
Validator.prototype.add = function (dom, rule, errorMsg) {
var ary = rule.split(':');
this.cache.push(function () {
var strategy = ary.shift(); // 刪除並返回數據第一個元素
ary.unshift(dom.value); // 向數組的開頭添加一個或更多元素,並返回新的長度
ary.push(errorMsg);
return strategies[strategy].apply(dom, ary);
});
}
Validator.prototype.start = function () {
for (var i = 0, validatorFunc; validatorFunc = this.cache[i++];) {
console.log(validatorFunc = this.cache[i++]);
var msg = validatorFunc();
if (msg) {
return msg;
}
}
}
var validatorFunc = function () {
var validator = new Validator();
validator.add(registerForm.userName, 'isNonEmpty', '用戶名不能爲空');
validator.add(registerForm.password, 'minLength:6', '密碼長度不能少於6位');
validator.add(registerForm.phoneNumber, 'isMobile', '手機號碼格式不正確');
return validator.start();
}
var registerForm = document.getElementById('registerForm');
registerForm.onsubmit = function () {
var errorMsg = validatorFunc();
if (errorMsg) {
alert(errorMsg);
return false;
}
}