设计模式学习(三):策略模式

策略模式

就是定义一系列算法,将他们封装起来,这些算法对应不同的策略实现。基于策略模式的程序,一般至少两部分组成,一部分是一组策略类,里面是具体的算法;第二个部分是环境类Context,Context接受客户的请求,随后把请求委托给某一个策略类。

策略模式的优缺点

优点:

  • 策略模式利用组合、委托和多态等技术和思想,可以有效地避免多重条件选择语句。

  • 策略模式提供了对开放—封闭原则的完美支持,将算法封装在独立的strategy 中,使得它们易于切换,易于理解,易于扩展。

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

缺点:

  • 要使用策略模式,必须了解所有的策略,必须了解各个策略 之间的不同点,这样才能选择一个合适的策略,这是违反最少知识原则的。

举个例子:用策略模式实现一个表单校验

<html>
    <body>
        <section>
            请输入用户名:<input type="text" name="userName" id="userName"/>
            请输入密码:<input type="text" name="password" id="passWord"/>
            请输入手机号码:<input type="text" name="phoneNumber" id="phoneNumber"/>
            <button id="submit">提交</button>
        </section>
    </body>
    <script>
        // 1、将校验逻辑封装成策略对象
        let strategies = {
            // 不为空
            isNonEmpty: (value, errorMsg) => {
                if (!value) {
                    return errorMsg
                }
            },
            // 限制最小长度
            minLength: (value, length, errorMsg) => {
                if ( value.length < length ){
                    return errorMsg
                }
            },
            // 是否是手机号
            isMobile: (value, errorMsg) => {
                if (!/(^1[0-9][0-9]{9}$)/.test( value )){
                    return errorMsg
                }
            }
        }
        // 2、维护一个实施校验规则的类
        class Validator {
            constructor () {
                // 保存校验规则
                this.validList = []
            }
            add (value, rules, errorMsg) {
                let self = this
                rules.forEach(ele => {
                    let strategyAry = ele.strategy.split( ':' )
                    let errorMsg = ele.errorMsg
                    self.validList.push(function(){
                        let strategy = strategyAry.shift()
                        strategyAry.unshift(value)
                        strategyAry.push( errorMsg )
                        const msg = strategies[strategy].apply(self, strategyAry)
                        return msg
                    })
                })
            }
            start () {
                let errorMsg
                this.validList.some(ele => {
                    let msg = ele()
                    if ( msg ){
                        return errorMsg = msg
                    }
                })
                return errorMsg
            }
        }
        // 调用校验规则
        const userName = document.getElementById('userName')
        const passWord = document.getElementById('passWord')
        const phoneNumber = document.getElementById('phoneNumber')
        const submit = document.getElementById('submit')
        
        let validataFunc = function(){
            let validator = new Validator()

            validator.add(userName.value, [{
                strategy: 'isNonEmpty',
                errorMsg: '用户名不能为空'
            }, {
                strategy: 'minLength:2',
                errorMsg: '用户名长度不能小于2位'
            }])

            validator.add(passWord.value, [{
                strategy: 'minLength:6',
                errorMsg: '密码长度不能小于6位'
            }])

            validator.add(phoneNumber.value, [{
                strategy: 'isMobile',
                errorMsg: '手机号码格式不正确'
            }])

            let errorMsg = validator.start()
            return errorMsg
        }

        submit.onclick = function(){
            let errorMsg = validataFunc()
            if ( errorMsg ){
                alert ( errorMsg )
                return false
            }
        }
        
    </script>
</html>
posted @ 2021-12-07 15:47  coderInside  阅读(40)  评论(0)    收藏  举报