Понимание шаблонов стратегии в JavaScript

внешний интерфейс алгоритм JavaScript jQuery

Понимание шаблона стратегии в javascript

Определение шаблона стратегии таково: определите серию алгоритмов, инкапсулируйте их один за другим и сделайте их взаимозаменяемыми.

Преимущества использования паттерна стратегии заключаются в следующем:

Преимущества: 1. Режим стратегии использует методы и идеи, такие как композиция и делегирование, чтобы эффективно избежать многих условных операторов.

2. Шаблон стратегии реализует принцип открытого-закрытого, что упрощает понимание и расширение кода.

3. Код шаблона стратегии можно использовать повторно.

1: Используйте режим стратегии для расчета бонуса;

Следующая демонстрация - это то, что я видел в книге, но это не имеет значения, мы просто должны понять, как использовать режим стратегии, мы можем использовать режим стратегии для расчета проблемы бонуса;

Например, сенсорный бонус компании оценивается на основе заработной платы и производительности работника. Для выступления A, бонус на конец года в 4 раза больше зарплаты, для выполнения B, бонус на конец года в 3 раза больше зарплаты, и Производительность для C. Бонус в год в год в 2 раза больше зарплаты; теперь мы используем общий метод кодирования и напишите код следующим образом:

var calculateBouns = function(salary,level) {
    if(level === 'A') {
        return salary * 4;
    }
    if(level === 'B') {
        return salary * 3;
    }
    if(level === 'C') {
        return salary * 2;
    }
};
// 调用如下:
console.log(calculateBouns(4000,'A')); // 16000
console.log(calculateBouns(2500,'B')); // 7500скопировать код

Первый параметр — это оклад, а второй параметр — грейд;

Недостатки кода следующие:

  1. Функция calculateBouns содержит множество операторов if-else.
  2. Функция calculateBouns негибкая.Если есть уровень D, то нам нужно добавить оператор if, чтобы судить об уровне D в функции calculateBouns;
  3. Повторное использование алгоритма плохое, если есть похожие алгоритмы в других местах, но правила другие, наши коды не могут быть использованы повсеместно.

2. Рефакторинг кода с использованием функций композиции

Функция объединения предназначена для инкапсуляции различных алгоритмов в небольшие функции. Например, если уровень А, инкапсулируется небольшая функция. Если уровень В, также инкапсулируется небольшая функция и т. д., следующий код:

var performanceA = function(salary) {
    return salary * 4;
};
var performanceB = function(salary) {
    return salary * 3;
};
        
var performanceC = function(salary) {
    return salary * 2
};
var calculateBouns = function(level,salary) {
    if(level === 'A') {
        return performanceA(salary);
    }
    if(level === 'B') {
        return performanceB(salary);
    }
    if(level === 'C') {
        return performanceC(salary);
    }
};
// 调用如下
console.log(calculateBouns('A',4500)); // 18000скопировать код

Код выглядит немного улучшенным, но все еще имеет следующие недостатки:

Функция calculateBouns может становиться все больше и больше, например, при повышении уровня D, и она неэластична.

   3. Рефакторинг кода с использованием шаблона стратегии

Режим стратегии относится к определению серии алгоритмов, инкапсуляции их один за другим и отделению неизменяемой части от измененной части, что фактически разделяет использование и реализацию алгоритма; способ использования алгоритма неизменен, все они основаны на по определенному алгоритму для получения рассчитанного бонусного числа, и реализация алгоритма основана на производительности, соответствующей различным правилам производительности;

Программа, основанная на режиме стратегии, состоит как минимум из двух частей: первая часть представляет собой набор классов стратегий, которые инкапсулируют определенные алгоритмы и отвечают за определенные процессы расчета. Вторая часть — это класс среды Context, который получает запрос клиента, а затем делегирует запрос определенному классу политики. Сначала мы используем традиционные объектно-ориентированные достижения;

Следующий код:

var performanceA = function(){};
performanceA.prototype.calculate = function(salary) {
    return salary * 4;
};
        
var performanceB = function(){};
performanceB.prototype.calculate = function(salary) {
    return salary * 3;
};

var performanceC = function(){};
performanceC.prototype.calculate = function(salary) {
    return salary * 2;
};
// 奖金类
var Bouns = function(){
    this.salary = null;    // 原始工资
    this.levelObj = null;  // 绩效等级对应的策略对象
};
Bouns.prototype.setSalary = function(salary) {
    this.salary = salary;  // 保存员工的原始工资
};
Bouns.prototype.setlevelObj = function(levelObj){
    this.levelObj = levelObj;  // 设置员工绩效等级对应的策略对象
};
// 取得奖金数
Bouns.prototype.getBouns = function(){
    // 把计算奖金的操作委托给对应的策略对象
    return this.levelObj.calculate(this.salary);
};
var bouns = new Bouns();
bouns.setSalary(10000);
bouns.setlevelObj(new performanceA()); // 设置策略对象
console.log(bouns.getBouns());  // 40000
        
bouns.setlevelObj(new performanceB()); // 设置策略对象
console.log(bouns.getBouns());  // 30000скопировать код

В приведенном выше коде используется шаблон стратегии для рефакторинга кода, вы можете видеть, что обязанности кода обновлены, и код стал более понятным.

4. Javascript-версия режима стратегии

код показывает, как показано ниже:

var obj = {
        "A": function(salary) {
            return salary * 4;
        },
        "B" : function(salary) {
            return salary * 3;
        },
        "C" : function(salary) {
            return salary * 2;
        } 
};
var calculateBouns =function(level,salary) {
    return obj[level](salary);
};
console.log(calculateBouns('A',10000)); // 40000скопировать код

Вы можете видеть, что код стал проще и понятнее;

Шаблон стратегии относится к определению серии алгоритмов и их инкапсуляции, но шаблон стратегии не только инкапсулирует алгоритмы, но также инкапсулирует ряд бизнес-правил Пока цели этих бизнес-правил непротиворечивы, мы можем использовать шаблон стратегии для инкапсулировать их;

проверка формы

Например, мы часто приходим к форме проверки, такой как диалоговое окно входа в систему, прежде чем мы войдем в систему, нам нужно выполнить операции проверки: например, есть следующая логика:

  1. Имя пользователя не может быть пустым
  2. Длина пароля не может быть меньше 6 символов.
  3. Мобильные номера должны соответствовать формату.

Например, HTML-код выглядит следующим образом:

<form action = "http://www.baidu.com" id="registerForm" method = "post">
        <p>
            <label>请输入用户名:</label>
            <input type="text" name="userName"/>
        </p>
        <p>
            <label>请输入密码:</label>
            <input type="text" name="password"/>
        </p>
        <p>
            <label>请输入手机号码:</label>
            <input type="text" name="phoneNumber"/>
        </p>
</form>скопировать код

Наш обычный код для написания проверки формы выглядит следующим образом:

var registerForm = document.getElementById("registerForm");
registerForm.onsubmit = function(){
    if(registerForm.userName.value === '') {
        alert('用户名不能为空');
        return;
    }
    if(registerForm.password.value.length < 6) {
        alert("密码的长度不能小于6位");
        return;
    }
    if(!/(^1[3|5|8][0-9]{9}$)/.test(registerForm.phoneNumber.value)) {
        alert("手机号码格式不正确");
        return;
    }
}скопировать код

Но такой способ написания кода имеет следующие недостатки:

  1. Функция registerForm.onsubmit относительно велика, а код содержит множество операторов if;
  2. Функции registerForm.onsubmit не хватает гибкости: если добавляется новое правило проверки или если мы хотим изменить проверку длины пароля с 6 до 8, мы должны изменить код внутри функции registerForm.onsubmit. Нарушает принцип открытого-закрытого.
  3. Повторное использование алгоритма оставляет желать лучшего, если в программу добавляется другая форма, эта форма также должна выполнять некоторые аналогичные тесты, тогда нам может понадобиться снова скопировать код;

Ниже мы можем использовать шаблон стратегии для рефакторов проверки формы;

Первым шагом является инкапсуляция объекта политики, следующий код:

var strategy = {
    isNotEmpty: function(value,errorMsg) {
        if(value === '') {
            return errorMsg;
        }
    },
    // 限制最小长度
    minLength: function(value,length,errorMsg) {
        if(value.length < length) {
            return errorMsg;
        }
    },
    // 手机号码格式
    mobileFormat: function(value,errorMsg) {
        if(!/(^1[3|5|8][0-9]{9}$)/.test(value)) {
            return errorMsg;
        }
    } 
};скопировать код

Далее мы собираемся реализовать класс Validator.Класс Validator здесь как контекст, отвечающий за получение пользовательских запросов и делегирование их объекту стратегии следующим образом:

var Validator = function(){
        this.cache = [];  // 保存效验规则
};
Validator.prototype.add = function(dom,rule,errorMsg) {
    var str = rule.split(":");
    this.cache.push(function(){
        // str 返回的是 minLength:6 
        var strategy = str.shift();
        str.unshift(dom.value); // 把input的value添加进参数列表
        str.push(errorMsg);  // 把errorMsg添加进参数列表
        return strategys[strategy].apply(dom,str);
    });
};
Validator.prototype.start = function(){
    for(var i = 0, validatorFunc; validatorFunc = this.cache[i++]; ) {
        var msg = validatorFunc(); // 开始效验 并取得效验后的返回信息
        if(msg) {
            return msg;
        }
    }
};скопировать код

Класс Validator выступает здесь как контекст, отвечающий за получение запроса пользователя и делегирование его объекту стратегии. В приведенном выше коде мы сначала создаем объект валидатора, а затем добавляем некоторые правила проверки к объекту валидатора с помощью метода validator.add, Метод validator.add получает 3 параметра следующим образом:

validator.add(registerForm.password,'minLength:6','длина пароля не может быть меньше 6 цифр');

registerForm.password — допустимый узел dom поля ввода;

minLength:6: это строка, разделенная двоеточием. minLength перед двоеточием представляет объект стратегии, выбранный клиентом, число 6 после двоеточия представляет параметры, которые должны быть проверены в процессе проверки, а minLength:6 означает валидация registerForm.Минимальная длина значения поля ввода текста пароля составляет 6 цифр, если строка не содержит двоеточия, это означает, что в процессе верификации не требуется никакой дополнительной проверочной информации;

Третий параметр — это сообщение об ошибке, возвращаемое в случае сбоя проверки;

Когда мы добавим ряд правил проверки в объект валидатора, мы вызовем метод validator.start(), чтобы начать проверку. Если validator.start() возвращает строку errorMsg в качестве возвращаемого значения, это означает, что проверка не прошла.В этом случае метод registerForm.onsubmit должен вернуть false, чтобы предотвратить отправку формы. Давайте посмотрим на код инициализации следующим образом:

var validateFunc = function(){
    var validator = new Validator(); // 创建一个Validator对象
    /* 添加一些效验规则 */
    validator.add(registerForm.userName,'isNotEmpty','用户名不能为空');
    validator.add(registerForm.password,'minLength:6','密码长度不能小于6位');
    validator.add(registerForm.userName,'mobileFormat','手机号码格式不正确');

    var errorMsg = validator.start(); // 获得效验结果
    return errorMsg; // 返回效验结果
};
var registerForm = document.getElementById("registerForm");
registerForm.onsubmit = function(){
    var errorMsg = validateFunc();
    if(errorMsg){
        alert(errorMsg);
        return false;
    }
}скопировать код

Вот весь код ниже:

var strategys = {
    isNotEmpty: function(value,errorMsg) {
        if(value === '') {
            return errorMsg;
        }
    },
    // 限制最小长度
    minLength: function(value,length,errorMsg) {
        if(value.length < length) {
            return errorMsg;
        }
    },
    // 手机号码格式
    mobileFormat: 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 str = rule.split(":");
    this.cache.push(function(){
        // str 返回的是 minLength:6 
        var strategy = str.shift();
        str.unshift(dom.value); // 把input的value添加进参数列表
        str.push(errorMsg);  // 把errorMsg添加进参数列表
        return strategys[strategy].apply(dom,str);
    });
};
Validator.prototype.start = function(){
    for(var i = 0, validatorFunc; validatorFunc = this.cache[i++]; ) {
        var msg = validatorFunc(); // 开始效验 并取得效验后的返回信息
        if(msg) {
            return msg;
        }
    }
};

var validateFunc = function(){
    var validator = new Validator(); // 创建一个Validator对象
    /* 添加一些效验规则 */
    validator.add(registerForm.userName,'isNotEmpty','用户名不能为空');
    validator.add(registerForm.password,'minLength:6','密码长度不能小于6位');
    validator.add(registerForm.userName,'mobileFormat','手机号码格式不正确');

    var errorMsg = validator.start(); // 获得效验结果
    return errorMsg; // 返回效验结果
};
var registerForm = document.getElementById("registerForm");
registerForm.onsubmit = function(){
    var errorMsg = validateFunc();
    if(errorMsg){
        alert(errorMsg);
        return false;
    }
};скопировать код

Как и выше, вы можете увидеть преимущества использования режима стратегии для написания кода проверки формы.Мы завершаем проверку формы, добавляя конфигурацию; в этом случае код может использоваться как компонент и может быть вызван в любое время. После изменения формы валидация также очень удобна для правил и может быть вызвана передачей параметров;

Добавить несколько правил проверки в поле ввода текста

Из приведенного выше кода видно, что мы можем соответствовать только одному правилу проверки для поля ввода.Например, мы можем только проверить, является ли поле ввода пустым или нет.

validator.add(registerForm.userName,'isNotEmpty','имя пользователя не может быть пустым');Но если мы хотим проверить, пусто ли поле ввода, а также убедиться, что длина поля ввода не меньше 10 цифр, то мы ожидаем, что нам потребуется передать такие параметры, как следующие:

validator.add(registerForm.userName,[{strategy:'isNotEmpty',errorMsg:'имя пользователя не может быть пустым'},{strategy:'minLength:6',errorMsg:'длина имени пользователя не может быть меньше 6 цифр'}])

Мы можем написать код следующим образом:

// 策略对象
var strategys = {
    isNotEmpty: function(value,errorMsg) {
        if(value === '') {
            return errorMsg;
        }
    },
    // 限制最小长度
    minLength: function(value,length,errorMsg) {
        if(value.length < length) {
            return errorMsg;
        }
    },
    // 手机号码格式
    mobileFormat: 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,rules) {
    var self = this;
    for(var i = 0, rule; rule = rules[i++]; ){
        (function(rule){
            var strategyAry = rule.strategy.split(":");
            var errorMsg = rule.errorMsg;
            self.cache.push(function(){
                var strategy = strategyAry.shift();
                strategyAry.unshift(dom.value);
                strategyAry.push(errorMsg);
                return strategys[strategy].apply(dom,strategyAry);
            });
        })(rule);
    }
};
Validator.prototype.start = function(){
    for(var i = 0, validatorFunc; validatorFunc = this.cache[i++]; ) {
    var msg = validatorFunc(); // 开始效验 并取得效验后的返回信息
    if(msg) {
        return msg;
    }
    }
};
// 代码调用
var registerForm = document.getElementById("registerForm");
var validateFunc = function(){
    var validator = new Validator(); // 创建一个Validator对象
    /* 添加一些效验规则 */
    validator.add(registerForm.userName,[
        {strategy: 'isNotEmpty',errorMsg:'用户名不能为空'},
        {strategy: 'minLength:6',errorMsg:'用户名长度不能小于6位'}
    ]);
    validator.add(registerForm.password,[
        {strategy: 'minLength:6',errorMsg:'密码长度不能小于6位'},
    ]);
    validator.add(registerForm.phoneNumber,[
        {strategy: 'mobileFormat',errorMsg:'手机号格式不正确'},
    ]);
    var errorMsg = validator.start(); // 获得效验结果
    return errorMsg; // 返回效验结果
};
// 点击确定提交
registerForm.onsubmit = function(){
    var errorMsg = validateFunc();
    if(errorMsg){
        alert(errorMsg);
        return false;
    }
}скопировать код

Уведомление:Вышеприведенный код весь сделан по книге, и это код книги. Самое главное, что мы понимаем реализацию режима стратегии. Например, функция проверки формы выше - это код, который инкапсулирован в таким образом. Мы обычно используем код проверки формы подключаемого модуля jquery, чтобы инкапсулировать его таким образом. По этой причине мы также можем использовать этот метод для инкапсуляции форм и другого обучения в будущем;