策略模式(Strategy):
策略模式:它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变换,不会影响到使用算法的客户端。
结构图:
实例 Dome
模拟一个商场不同打折收费,策略模式与简单工厂结合
收费抽象类及其实现的子类:
/// <summary>
/// 现金收费抽象类
/// </summary>
public abstract class CashSuper
{
public abstract double AcceptCash(double money);
}
/// <summary>
/// 正常收费子类
/// </summary>
class CashNormal : CashSuper
{
public override double AcceptCash(double money)
{
return money;
}
}
/// <summary>
/// 打折收费子类
/// </summary>
class CashRebate : CashSuper
{
/// <summary>
/// 打折率
/// </summary>
public double MoneyRebate { get; set; } = 1d;
public CashRebate(double rebate)
{
this.MoneyRebate = rebate;
}
public override double AcceptCash(double money)
{
return money * MoneyRebate;
}
}
/// <summary>
/// 返利模式收费子类
/// </summary>
class CashReturn : CashSuper
{
private double moenyCondition = 0.0d;
private double moenyReturn = 0.0d;
public double MoenyCondition { get => moenyCondition; set => moenyCondition = value; }
public double MoenyReturn { get => moenyReturn; set => moenyReturn = value; }
public CashReturn(double mc,double mr)
{
this.moenyCondition = mc;
this.moenyReturn = mr;
}
public override double AcceptCash(double money)
{
double result = money;
if(money>=moenyCondition)
{
result = money - Math.Floor(money / moenyCondition) * moenyReturn;
}
return result;
}
}
工厂模式和策略模式结合:
/// <summary>
/// 工厂模式和策略模式结合
/// </summary>
public class CashContext
{
CashSuper cs = null;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="type">收费类型</param>
public CashContext(string type)
{
switch(type)
{
case "正常":
Cs = new CashNormal();
break;
case "返利":
Cs = new CashReturn(300, 100);
break;
case "打折":
Cs = new CashRebate(0.8);
break;
default:
break;
}
}
public CashSuper Cs { get => cs; set => cs = value; }
public double GetResult(double money)
{
if(Cs!=null)
{
return Cs.AcceptCash(money);
}
else
{
Console.WriteLine("未找到收费类型");
return double.MaxValue;
}
}
}
客户端调用:
static void Main(string[] args)
{
//策略模式与简单工厂结合使用 :客户端只需识别一个类,CashContext
CashContext cs = new CashContext("返利"); //输入不同的模式,返回不同的收费模式
double d= cs.GetResult(500);
Console.WriteLine(d);
Console.ReadKey();
}
策略模式解析:
- 策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有算法,减少了各种算法类与使用算法类之间的耦合。
- 策略模式的 Strategy 类层次为 Context 定义了一系列的可重用算法或行为。继承有助于提起出这些算法中的公共功能。
- 对于本例中的公共功能就是得到实际收费的计算方法:GetResult() ; 这使得算法之间有了抽象的父类。
- 策略模式的优点是简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。
- 在工厂中用到了 switch 条件分支,是因为当不同的行为堆砌在一个类中时,就很难免使用条件语句来选择合适的行为。将这些分支封装在独立的 Strategy类中,可以在使用这些行为的类中消除条件语句。就本例而言,客户端的代码就消除了条件语句,避免了大量的判断。总之,策略模式封装了变化。
- 如果要增加算法,还要改动 CashContext 类中的 条件判断代码,可以利用反射将改动降低到最小化。