设计模式 - 策略模式

策略模式指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。

策略模式定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。

 将不变的部分和变化的部分隔开是每个设计模式的主题。策略模式的目的就是将算法的实现和算法的使用分离开来。

 

策略模式包含三个角色:

  Context:环境类

  Strategy:抽象策略类

  ConcreteStrategy:具体抽象类

 

例子:

 策略模式在js中最常见、使用最多的就是多重表单校验功能

  1 <html>
  2 <head>
  3     <title>策略模式-校验表单</title>
  4     <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  5 </head>
  6 
  7 <body>
  8     <form id="registerForm" method="post" action="">
  9         用户名:
 10         <input type="text" name="userName"> 密码:
 11         <input type="text" name="password"> 手机号码:
 12         <input type="text" name="phoneNumber">
 13         <button type="submit">提交</button>
 14     </form>
 15 
 16     <script>
 17         // 策略对象
 18         let strategies = {
 19             isNoEmpty: function (value, errorMsg) {
 20                 if (value === '') {
 21                     return errorMsg;
 22                 }
 23             },
 24             isNoSpace: function (value, errorMsg) {
 25                 if (value.trim() === '') {
 26                     return errorMsg;
 27                 }
 28             },
 29             minLength: function (value, length, errorMsg) {
 30                 if (value.trim().length < length) {
 31                     return errorMsg;
 32                 }
 33             },
 34             maxLength: function (value, length, errorMsg) {
 35                 if (value.length > length) {
 36                     return errorMsg;
 37                 }
 38             },
 39             isMobile: function (value, errorMsg) {
 40                 if (!/^1[3456789]\d{9}$/.test(value)) {
 41                     return errorMsg;
 42                 }
 43             }
 44         }
 45 
 46 
 47         class Validator{
 48             constructor(){
 49                 this.cache = [];
 50             }
 51         }
 52         
 53 
 54         Validator.prototype.add = function (dom, rules) {
 55             let self = this;
 56             for (let i = 0, rule; rule = rules[i++];) {
 57                 (function (rule) {
 58                     var strategyAry = rule.strategy.split(':');
 59                     var errorMsg = rule.errorMsg;
 60                     self.cache.push(function () {
 61                         var strategy = strategyAry.shift();
 62                         strategyAry.unshift(dom.value);
 63                         strategyAry.push(errorMsg);
 64                         return strategies[strategy].apply(dom, strategyAry);
 65                     })
 66                 })(rule)
 67             }
 68         };
 69 
 70         Validator.prototype.start = function () {
 71             for (let i = 0, validatorFunc; validatorFunc = this.cache[i++];) {
 72                 let errorMsg = validatorFunc();
 73                 if (errorMsg) {
 74                     return errorMsg;
 75                 }
 76             }
 77         };
 78 
 79         
 80         let validataFunc = function () {
 81             var validator = new Validator();
 82             // 用户名
 83             validator.add(registerForm.userName, [{
 84                 strategy: 'isNoEmpty',
 85                 errorMsg: '用户名不可为空'
 86             }, {
 87                 strategy: 'isNoSpace',
 88                 errorMsg: '不允许以空白字符命名'
 89             }, {
 90                 strategy: 'minLength:2',
 91                 errorMsg: '用户名长度不能小于2位'
 92             }]);
 93 
 94             //密码
 95             validator.add(registerForm.password, [{
 96                 strategy: 'minLength:6',
 97                 errorMsg: '密码长度不能小于6位'
 98             }]);
 99 
100             //手机号
101             validator.add(registerForm.phoneNumber, [{
102                 strategy: 'isMobile',
103                 errorMsg: '请输入正确的手机号码格式'
104             }]);
105             let errorMsg = validator.start();
106             return errorMsg;
107         }
108 
109 
110         // 调用代码
111         let registerForm = document.getElementById('registerForm');
112         registerForm.onsubmit = function () {
113             let errorMsg = validataFunc();
114             if (errorMsg) {
115                 alert(errorMsg);
116                 return false;
117             }
118         }
119     </script>
120 </body>
121 
122 </html>

 

优点

  1.策略模式可以有效的避免多层判断语句

  2.策略模式讲每个算法独立封装,易于理解和拓展,对"开闭原则"完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。

  3.策略模式中的算法也可以复用在系统的其它地方,从而避免许多重复的复制粘贴工作。

缺点

  1.要使用策略模式,必须要知道全部的策略类,这样才能找到合适的策略类

  2.策略模式会定义很多策略对象和策略类

 

策略模式与js

  在JS中除了使用类来封装算法之外,也可以通过函数来实现。实际上在JS中,策略模式已经融合到了语言本身当中,我们经常使用函数来封装不同的行为和算法,并且将他传入到另一个函数中。没当我们调用这些函数的时候,不同的函数会返回不同的结果,所以其实策略模式在JS中就成了一种隐形的模式。

posted @ 2019-06-23 20:04  哒哒呵~  阅读(206)  评论(0编辑  收藏  举报