初识
策略模式(Strategy):它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。是一种行为型模式。
理解:策略模式将每种算法进行封装,并让算法继承于抽象超类。在使用算法的环境中针对抽象策略类,而不是针对具体算法,符合开放-封闭原则。
结构图
角色:
(1)Context(环境类):负责使用算法策略,其中维持了一个抽象策略类的引用实例。
(2)Strategy(抽象策略类):所有策略类的父类,为所支持的策略算法声明了抽象方法。=> 既可以是抽象类也可以是接口
(3)ConcreteStrategy(具体策略类):实现了在抽象策略类中声明的方法。
应用
Background:某公司为某商场做收银软件,商场不定时有促销活动,活动形式又不限。假设现有三种营销方式:
1、原价
2、消费满300返100
3、消费打8折
结构图:
实现
double total = 0.0d;
private void btnOK_Click(object sender, EventArgs e)
{
CashContext csuper = new CashContext(cbxType.SelectedItem.ToString());
double totalPrices = 0d;
totalPrices = csuper.GetResult(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));
total += totalPrices;
lbxList.Items.Add("单价:" + txtPrice.Text + "数量:" + txtNum.Text + " " + cbxType.SelectedItem + " 合计" + totalPrices.ToString());
lblResult.Text = total.ToString();
}
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 CashContext
{
CashSuper cs = null;
public CashContext(string type)
{
switch (type)//根据客户选择的收费方式,进行收费
{
case "正常收费":
CashNormal cs0 = new CashNormal();
cs = cs0;
break;
case "满300返100":
CashReturn cs1 = new CashReturn("300", "100");
cs = cs1;
break;
case "打8折":
CashRebate cs2 = new CashRebate("0.8");
cs = cs2;
break;
}
}
public double GetResult(double money)
{
return cs.acceptCash(money);
}
}
优点
(1)提供了对开闭原则的完美支持,用户可以在不修改原有系统的基础上选择具体算法或行为,也可以灵活地增加新的算法或行为。
(2)避免了多重的if-else条件选择语句,利于系统的维护。
(3)提供了一种算法的复用机制,不同的环境类可以方便地复用这些策略类。
缺点
(1)客户端需要知道所有的策略类,并自行决定使用哪一个策略 => 只适用于客户端了解所有策略算法的情况。
(2)将造成系统产生很多的具体策略类,任何细小的变化都将导致系统要增加一个具体策略类 => 类的个数也许会超出预期。
(3)无法在客户端同时使用多个策略类 => 客户端每次只能使用一个策略类。
应用场景
(1)如果一个系统要动态地在几种算法之间选择其中一种 => 那就快用策略模式吧骚年!
(2)如果有难以维护的多重if-else条件选择语句是为了实现对象的行为 => 那就快用策略模式吧骚年!
(3)不希望客户知道复杂的与算法有关的数据结构,可以将其封装到策略中 => 提高算法的保密性和安全性!