js策略模式

策略模式定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化不会影响到使用算法的客户。

策略模式类图:

该模式涉及到三个角色:

  • 环境角色(Context):持有一个Strategy类的引用
  • 抽象策略角色(Strategy):这是一个抽象角色,通常由一个接口或抽象类来实现。此角色给出所有具体策略类所需实现的接口。
  • 具体策略角色(ConcreteStrategy):包装了相关算法或行为。

先上C#版本:

namespace 策略模式
{
    //现金收取父类
    abstract class CashSuper
    {
        //抽象方法:收取现金,参数为原价,返回为当前价
        public abstract double acceptCash(double money);
    }
}
namespace 策略模式
{
    //正常收费,继承CashSuper
    class CashNormal : CashSuper
    {
        public override double acceptCash(double money)
        {
            return money;
        }
    }
}
namespace 策略模式
{
    //打折收费,继承CashSuper
    class CashRebate : CashSuper
    {
        private double moneyRebate = 1d;
        //初始化时,必需要输入折扣率,如八折,就是0.8
        public CashRebate(string moneyRebate)
        {
            this.moneyRebate = double.Parse(moneyRebate);
        }

        public override double acceptCash(double money)
        {
            return money * moneyRebate;
        }
    }
}
namespace 策略模式
{
    //返利收费,继承CashSuper
    class CashReturn : CashSuper
    {
        private double moneyCondition = 0.0d;
        private double moneyReturn = 0.0d;
        //初始化时必须要输入返利条件和返利值,比如满300返100,则moneyCondition为300,moneyReturn为100
        public CashReturn(string moneyCondition, string moneyReturn)
        {
            this.moneyCondition = double.Parse(moneyCondition);
            this.moneyReturn = double.Parse(moneyReturn);
        }

        public override double acceptCash(double money)
        {
            double result = money;
            //若大于返利条件,则需要减去返利值
            if (money >= moneyCondition)
                result = money - Math.Floor(money / moneyCondition) * moneyReturn;

            return result;
        }
    }
}
namespace 策略模式
{
    //现金收取工厂
    class CashContext
    {
        CashSuper cs = null;

        //根据条件返回相应的对象
        public CashContext(string type)
        {
            switch (type)
            {
                case "正常收费":
                    cs = new CashNormal();
                    break;
                case "满300返100":
                    cs = new CashReturn("300", "100");
                    break;
                case "打8折":
                    cs = new CashRebate("0.8");
                    break;
            }
        }

        public double GetResult(double money)
        {
            return cs.acceptCash(money);
        }
    }
}
//调用:
CashContext csuper = new CashContext(cbxType.SelectedItem.ToString());
totalPrices = csuper.GetResult(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));
lbxList.Items.Add("单价:" + txtPrice.Text + " 数量:" + txtNum.Text + " "
                + cbxType.SelectedItem + " 合计:" + totalPrices.ToString());

js模拟C#的策略模式:

//现金收取父类
    var CashSuper = function(){};
    CashSuper.prototype.acceptCash = function(money){
        throw new Error('具体实现必须由子类重写');
    };

    //正常收费,继承CashSuper
    var CashNormal = function(){};
    CashNormal.prototype = new CashSuper();
    CashNormal.prototype.acceptCash = function(money){
         return money;
    };

    //打折收费,继承CashSuper
    var CashRebate = function(moneyRebate){
        this.moneyRebate = moneyRebate;
    };
    CashRebate.prototype = new CashSuper();
    CashRebate.prototype.acceptCash = function(money){
         return money * this.moneyRebate;
    };

    //返利收费,继承CashSuper
    var CashReturn = function(moneyCondition,moneyReturn){
        this.moneyCondition = moneyCondition;
        this.moneyReturn = moneyReturn;
    };
    CashReturn.prototype = new CashSuper();
    CashReturn.prototype.acceptCash = function(money){
        var result = money;

        ////若大于返利条件,则需要减去返利值
        if (money >= this.moneyCondition)
            result = money - money / this.moneyCondition * this.moneyReturn;
        return result;
    };

    //现金收取工厂
    var CashContext = function(type){
        this.cs;
        switch(type){
            case '正常收费':
                this.cs = new CashNormal();
            break;
            case '满300返100':
                this.cs = new CashReturn(300,100);
            break;
            case '打8折':
                this.cs = new CashRebate(0.8);
            break;
        }
    };
    CashContext.prototype.getResult = function(money){
        return this.cs.acceptCash(money);
    };

    //调用:
    var type = '满300返100', //计算方式
        price = 300, //单价
        num = 2; //数量

    var csuper = new CashContext(type);
    var totalPrices = csuper.getResult(price * num);
    alert('单价:' + price + ',数量:' + num + ',计算方式:' + type + ',合计:' + totalPrices);

js特性实现策略模式:

//策略对象
    var cashStrategy = {

        //正常收费
        cashNormal:function(){
            return this.money;
        },

        //打折收费
        cashRebate:function(moneyRebate){
            return this.money * moneyRebate;
        },

        //返利收费
        cashReturn:function(moneyCondition,moneyReturn){
            var result = this.money;

            ////若大于返利条件,则需要减去返利值
            if (this.money >= moneyCondition)
                result = this.money - this.money / moneyCondition * moneyReturn;
            return result;
        }
    };
    
    //策略工厂
    var CashContext = (function(){

        //收取现金
        var acceptCash = function(type){

            var args = [].slice.call(arguments,1);

            return function(money){
                this.money = money;
                return cashStrategy[type].apply(this,args);
            };
        };

        var Fn = function(type){

            this.cs = null;

            switch(type){
                case '正常收费':
                    this.cs = acceptCash('cashNormal');
                break;
                case '打8折':
                    this.cs = acceptCash('cashRebate',0.8);
                break;
                case '满300返100':
                    this.cs = acceptCash('cashReturn',300,100);
                break;
            }
        };

        Fn.prototype.getResult = function(money){
            return this.cs.call(this,money);
        };

        return Fn;
    })();

    //调用:
    var type = '满300返100', //计算方式
        price = 300, //单价
        num = 2; //数量

    var csuper = new CashContext(type);
    var totalPrices = csuper.getResult(price * num);
    alert('单价:' + price + ',数量:' + num + ',计算方式:' + type + ',合计:' + totalPrices);

总结:js利用字典匹配就能轻松实现策略模式,由于他是动态语言不少模式是隐含的天生具有的,策略模式也是一个简单到不能算模式的模式。

原文地址:https://www.cnblogs.com/gongshunkai/p/6574952.html