策略模式

来源:互联网 发布:misumi 选型软件 编辑:程序博客网 时间:2024/06/05 20:51

策略模式


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

          面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类。

          商场促销,使用简单工厂模式实现:

<strong><span style="font-size:24px;">//简单工厂模式的实现://现金收费抽象类abstract class CashSuper{    public abstract double acceptCash(double money);}//正常收费子类class CashNormal : CashSuper {    public override double acceptCash(double money)    {        return money;    }}//打折收费子类class CashRebate:CashSuper {    private double moneyRebate=1d;    public CashRebate (string moneyRebate)    {        this .moneyRebate =double .Parse (moneyRebate );    }    public override double acceptCash(double money)    {        return money *moneyRebate ;    }}//返利收费子类class CashReturn:CashSuper {    private double moneyCondition=0.0d;    private double moneyReturn=0.0d;    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;    }}//现金收费工厂类class CashFactory{    public static CashSuper createCashAccept(string type)    {        CashSuper cs=null;        switch (type )        {            case "正常收费":                cs =new CashNormal ();                break ;            case "满300返100":                CashReturn cr1= new CashReturn  ("300","100");                cs =cr1;                break ;            case "打8折":                CashRebate cr2=new CashRebate ("0.8");                cs =cr2 ;                break ;        }        return cs ;    }}        //简单工厂模式客户端代码:        //double total = 0.0d;        //private void btnOk_Click(object sender, EventArgs e)        //{        //    CashSuper csuper = CashFactory.createCashAccept(cbxType.SelectedItem.ToString());        //    double totalPrices = 0d;        //    totalPrices = csuper.acceptCash(Convert.ToDouble(txtprice.Text)        //        * Convert.ToDouble(txtnum.Text));        //    total =total +totalPrices ;        //    lbxList .Items.Add("单价:"+txtprice .Text +"数量:"+txtnum .Text+""        //        +cbxType.SelectedItem+"合计:"+totalPrices .ToString ());        //    lblResult .Text =total.ToString ();</span></strong>

          策略模式的结构:

          Strategy类,定义所有支持的算法的公共接口

<strong><span style="font-size:24px;">//抽象算法类abstract class Strategy{    //算法方法    public abstract void AlgorithmInterface();}</span></strong>

          ConcreteStrategy,封装了具体的算法或行为,继承于Strategy

<strong><span style="font-size:24px;">//具体算法Aclass ConcreteStrategyA:Strategy {    //算法A实现方法    public override void AlgorithmInterface()    {        Console .WriteLine ("算法A实现");    }}//具体算法Bclass ConcreteStrategyB:Strategy {    //算法B实现方法    public override void AlgorithmInterface()    {        Console .WriteLine ("算法B实现");    }}//具体算法Cclass ConcreteStrategyC:Strategy {    //算法C实现方法    public override void AlgorithmInterface()    {        Console .WriteLine ("算法C实现");    }}</span></strong>

          Context,用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用。

<strong><span style="font-size:24px;">//上下文class Context{    Strategy strategy;    public Context (Strategy strategy)    {        this .strategy =strategy ;    }    //上下文接口    public void ContextInterface()    {        strategy .AlgorithmInterface ();    }}        //策略模式客户端代码        static void Main(string[] args)        {            Context context;            context = new Context(new ConcreteStrategyA());            context.ContextInterface();            context = new Context(new ConcreteStrategyB());            context.ContextInterface();            context = new Context(new ConcreteStrategyC());            context.ContextInterface();            Console.Read();        }</span></strong>

          策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。

          策略模式的Sstrategy类层次为Context定义了一系列的可供重用的算法或行为,继承有助于析取除这些算法中的公共功能。

另外一个优点是,简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口独立测试。

          当不同的行为堆砌在一个类中时,就很难避免使用条件语句来选择合适的行为,将这些行为封装在一个个独立的Strategy类中,可以在使用这些行为的类中消除条件语句。

          策略模式下的商场促销程序,在简单工厂模式的基础上,原来写的CashSuper、CashNormal、CashRebate和CashReturn都不用修改,只要添加一个CashContext类,并且修改客户端就可以实现:

<strong><span style="font-size:24px;">//CashContext类class CashContext{    private CashSuper cs;    public CashContext(CashSuper csuper)    {        this.cs = csuper;    }    public double GetResult(double money)    {        return cs.acceptCash(money);    }}        //策略模式客户端代码:        double total = 0.0d;        private void btnOK_Click(object sender, EventArgs e)        {            CashContext cc = null;            switch (cbxType.SelectedItem.ToString())            {                case "正常收费":                    cc = new CashContext(new CashNormal());                    break;                case "满300返100":                    cc = new CashContext(new CashReturn("300", "100"));                    break;                case "打8折":                    cc = new CashContext(new CashRebate("0.8"));                    break;            }            double totalPrice = 0d;            totalPrice = cc.GetResult (Convert.ToDouble(txtprice.Text)                * Convert.ToDouble(txtnum.Text));            total = total + totalPrice;            lbxList.Items.Add("单价:" + txtprice.Text + "数量:" + txtnum.Text + ""                + cbxType.SelectedItem + "合计:" + totalPrice.ToString());            lblResult.Text = total.ToString();        }</span></strong>

          简单工厂和策略模式相结合:

<strong><span style="font-size:24px;">//改造后的CashContextclass CashContext{    CashSuper cs = null;    public CashContext(string type)    {        switch (type)        {            case "正常收费":                CashNormal cs0 = new CashNormal();                cs = cs0;                break;            case "满300返100":                CashReturn cr1 = new CashReturn("300", "100");                cs = cr1;                break;            case "打8折":                CashRebate cr2 = new CashRebate("0.8");                cs = cr2;                break;        }    }    public double GetResult(double money)    {        return cs.acceptCash(money);    }}        //策略结合简单工厂        double total = 0.0d;        private void btnOk_Click(object sender, EventArgs e)        {            CashContext csuper = new CashContext(cbxType.SelectedItem.ToString());            double totalParices = 0d;            totalParices = csuper.GetResult(Convert.ToDouble(txtprice.Text) * Convert.ToDouble(txtnum.Text));            total = total + totalParices;            lbxList.Items.Add("单价:" + txtprice.Text + "数量:" + txtnum.Text + ""                + cbxType.SelectedItem + "合计:" + totalParices.ToString());            lblResult.Text = total.ToString();        }</span></strong>

          策略模式就是用来封装算法的,但在实践中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。

          在基本的策略模式中,选择所用具体实现的职责有客户端对象承担,并转给策略模式的Context对象,这本身并没有解除客户端需要选择判断的压力,而策略模式与简单工厂模式结合后,选择具体实现的职责也可以由Context来承担,这就最大化的减轻了客户端的职责。



2 0