• 策略模式可以有效避免多重条件选择语句。
    • 策略模式提供了对开放-封装原则的完美支持,将方法封装在独立的strategy中,使得它们易于切换,易于理解,易于扩展。
    • 复用性高

    策略模式也有一些缺点

    • 增加了许多策略类或者策略对象。
    • 要使用策略模式,必须了解所有的strategy,违反了最少知识原则

    用策略模式重构表单校验

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