javascript設計模式學習筆記之策略模式

策略模式

  • 策略模式指的是 定義一系列的算法,把它們一個個封裝起來,將不變的部分和變化的部分隔開,實際就是將算法的使用和實現分離出來, 這樣就能避免不少的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;
            }
        }
  • 以上的代碼都是在個人github上能夠看到
相關文章
相關標籤/搜索