大话设计模式之策略模式

 在做一件事情完成一项任务时,往往会有很多个方法,这每一种方法都可以被称为策略,我们会根据不同的环境或条件,从众多方法中选取一个合适的方法来完成这件事情或任务。就像我们过年回家,回家的方式有很多种,比如坐飞机、乘坐火车、坐客车、走路等等,但是由于自身条件限制或者环境限制,我们往往会选择一个比较适合自己的回家方式回家。而我们选用的这个方法就可以称之为策略。

        其实所谓的策略模式,是一种对象行为型模式,它定义了算法家族,然后分别对算法封装,让算法之间可以相互替换。这个模式让算法的变化,不会影响到使用算法的客户。它也被称之为政策模式。

策略模式的结构图:

              

Strategy类:

       为Context定义了一系列的可以被重用的算法或者行为。

ConcreteStrategy类:

         具体策略类,它封装了具体的算法或行为,继承Strategy类,有助于析取出这些算法中的公共功能。

策略模式应用举例:

        代码结构图:

             

       窗体设计图:

                

     代码实现:     

[csharp]  view plain copy
  1. double total = 0.0d;  
  2.         private void btnOK_Click(object sender, EventArgs e)  
  3.         {  
  4.             CashContext csuper = new CashContext(cmbType.SelectedItem.ToString());          
  5.              double totalPrices = 0d;  
  6.             totalPrices = csuper . GetResult (Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));  
  7.             total = total + totalPrices;  
  8.             listBox1.Items.Add("单价:" + txtPrice.Text + "数量:" + txtNum.Text + "合计:" + totalPrices.ToString());  
  9.             lblTotal.Text =Convert .ToString  ( total) ;  
  10.         }  
  11.   
  12.         private void btnRef_Click(object sender, EventArgs e)  
  13.         {  
  14.             txtPrice.Text = "";  
  15.             txtNum.Text = "";  
  16.             listBox1.Text = "";  
  17.             lblTotal.Text = "";  
  18.         }  
  19.   
  20.         private void Form1_Load(object sender, EventArgs e)  
  21.         {  
  22.             cmbType.Items .AddRange (new object []{"正常收费","打八折","打七折","打五折","满300返100"});  
  23.             cmbType.SelectedIndex = 0;  
  24.         }  
  25.     }  
  26.     class CashContext  
  27.     {  
  28.         CashSuper cs = null;  
  29.         public CashContext(string type)//string type不是具体的收费策略,而是一个字符串,表示收费类型  
  30.         {  
  31.             switch (type )  
  32.             {  
  33.                 case "正常收费":  
  34.                     CashNormal cs0 = new CashNormal();  
  35.                     cs = cs0;  
  36.                     break;  
  37.                 case "满300返100":  
  38.                     CashReturn cs1 = new CashReturn("300","100");  
  39.                     cs = cs1;  
  40.                     break;  
  41.                 case "打八折":  
  42.                     CashRebate cs2 = new CashRebate("0.8");  
  43.                     cs = cs2;  
  44.                     break;  
  45.             }  
  46.         }  
  47.         public double GetResult(double money)  
  48.         {  
  49.             return cs.acceptCash(money);  
  50.         }  
  51.     }  
  52.   
  53.     abstract class CashSuper  //现金收取的抽象类  
  54.     {  
  55.         public abstract double acceptCash(double money);  
  56.     }  
  57.   
  58.     class CashNormal : CashSuper   //子类之正常收费类  
  59.     {  
  60.         public override double acceptCash(double money)  
  61.         {  
  62.             return money;  
  63.         }  
  64.     }  
  65.   
  66.     class CashRebate : CashSuper   //打折收费类  
  67.     {  
  68.         private double moneyRebate = 1d;  
  69.         public CashRebate  (string moneyRebate)  
  70.         {  
  71.             this.moneyRebate = double.Parse(moneyRebate);  
  72.         }  
  73.         public override double acceptCash(double money)  
  74.         {  
  75.             return money * moneyRebate;  
  76.         }  
  77.     }  
  78.   
  79.     class CashReturn : CashSuper  //满多少返回多少类  
  80.     {  
  81.         private double moneyCondition = 0.0d;  
  82.         private double moneyReturn = 0.0d;  
  83.         public CashReturn(string moneyCondition, string moneyReturn)  
  84.         {  
  85.             this.moneyCondition = double.Parse(moneyCondition);  
  86.             this.moneyReturn = double.Parse(moneyReturn);  
  87.         }  
  88.         public override double acceptCash(double money)  
  89.         {  
  90.             double result = money;  
  91.             if (money >= moneyCondition)  
  92.                 result = money - moneyReturn;  
  93.             return result;  
  94.         }  
  95.     }   

策略模式的适用:

        第一:如果一个系统中有很多类,而他们的区别也只是在于他们的行为,这时就可以使用策略模式从众多行为中选取其中一种行为。

       第二:一个系统需要动态的从多种算法中选取某一种算法。

       第三:系统有复杂的、与算法相关的数据结构,而我们又不希望客户端的客户知道这些数据结构,在具体策略中封装算法和相关数据结构,以确保算法的安全性,对算法保密。

       第四:当不同的行为堆放在一个类中,就难免在执行时,会使用条件语句来选择某一种合适的行为。

策略模式的优点:

       第一:简化了单元测试,每个算法都有自己的类,可以通过自己的接口来单独测试。

       第二:可以避免使用多重条件转移语句,使之易维护。

       第三:策略模式定义了一系列算法行为,所有算法完成的都是相同工作,只是实现不同,它可以以相同方式调用所有算法,减少各种与使用算法类之间的耦合。

### C++ 中的策略模式 #### 策略模式概述 策略模式是一种行为型设计模式,它定义了一系列算法,并将每个算法封装起来,使它们可以互换。这种模式使得算法可以在不影响客户端的情况下发生变化[^3]。 #### UML 图解 在策略模式中,通常有一个上下文(Context)类用于维持对某个具体策略(Concrete Strategy)实例的引用。而所有的具体策略都实现了相同的接口(Strategies Interface),这允许Context能够调用任何具体的策略而不必关心其内部细节[^4]。 #### 实现步骤 为了实现这一模式,在C++里首先要创建一个表示不同策略的行为接口: ```cpp // 定义策略基类 class IStrategy { public: virtual ~IStrategy() {} virtual void execute() const = 0; }; ``` 接着为各种可能的具体操作提供多个派生自`IStrategy`的不同版本: ```cpp // 具体策略A class ConcreteStrategyA : public IStrategy { public: void execute() const override { std::cout << "Executing strategy A\n"; } }; // 具体策略B class ConcreteStrategyB : public IStrategy { public: void execute() const override { std::cout << "Executing strategy B\n"; } }; ``` 最后构建一个持有并能切换当前所使用的策略的对象——即所谓的“环境”或“上下文”。 ```cpp // 上下文类 class Context { private: IStrategy* _strategy; public: // 构造函数接收一个初始策略 explicit Context(IStrategy& s):_strategy(&s){} // 设置新的策略 void set_strategy(IStrategy& new_strategy){ _strategy=&new_strategy; } // 执行选定的策略 void perform_operation(){ if (_strategy != nullptr) _strategy->execute(); else std::cerr<<"No strategy selected.\n"; } }; ``` 这样就完成了简单的策略模式框架搭建。当需求改变时只需新增加对应的策略类即可满足扩展性的要求[^5]。
评论 38
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值