策略模式(Strategy Pattern)
策略模式定义了一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。别名:Policy(方针)
结构:
代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyStrategy
{
abstract class Strategy
{
public abstract void AlgorithmInterface();
}
class ConcreteStrategyA : Strategy
{
public override void AlgorithmInterface()
{
Console.WriteLine("Algorithm A implementation");
}
}
class ConcreteStrategyB : Strategy
{
public override void AlgorithmInterface()
{
Console.WriteLine("Algorithm B implementation");
}
}
class ConcreteStrategyC : Strategy
{
public override void AlgorithmInterface()
{
Console.WriteLine("Algorithm C implementation");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyStrategy
{
class Context
{
private Strategy strategy;
public Context(Strategy strategy)
{
this.strategy = strategy;
}
public void ContextInterface()
{
strategy.AlgorithmInterface();
}
}
}using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyStrategy
{
class Program
{
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.ReadKey();
}
}
}
参与者:Strategy( 策略 )
— 定义所有支持的算法的公共接口。 Context使用这个接口来调用某ConcreteStrategy定义的算法。
• ConcreteStrategy(具体策略)
— 以Strategy接口实现某具体算法。
• Context(上下文)
— 用一个ConcreteStrategy对象来配置。
— 维护一个对Strategy对象的引用。
— 可定义一个接口来让Strategy访问它的数据。
效果:
1)相关算法系列Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法中的公共功能。
2) 一个替代继承的方法。继承提供了另一种支持多种算法或行为的方法。你可以直接生成一个Context类的子类,从而给它以不同的行为。但这会将行为硬行编制到 Context中,而将算法的实现与Context的实现混合起来 , 从而使Context难以理解、难以维护和难以扩展,而且还不能动态地改变算法。最后你得到一堆相关的类 , 它们之间的唯一差别是它们所使用的算法或行为。将算法封装在独立的Strategy类中使得你可以独立于其Context改变它,使它易于切换、易于理解、易于扩展。
3) 消除了一些条件语句。Strategy模式提供了用条件语句选择所需的行为以外的另一种选择。当不同的行为堆砌在一个类中时 , 很难避免使用条件语句来选择合适的行为。将行为封装在一个个独立的Strategy类中消除了这些条件语句。
实现:
1)定义Strategy和Context接口
一种办法是让Context将数据放在参数中传递给Strategy操作——也就是说, 将数据发送给Strategy。这使得Strategy和Context解耦。另一种办法是让Context将自身作为一个参数传递给Strategy, 该Strategy再显式地向该Context请求数据。或者,Strategy可以存储对它的Context的一个引用, 这样根本不再需要传递任何东西。
2)将Strategy作为模板参数
template <class AStrategy>
class Context
{
public
void Operation()
{
theStrategy.DoAlgorithm();
}
private:
AStrategy theStrategy;
}
class MyStrategy
{
public:
void DoAlgorithm();
}
Context<MyStrategy> myContext;
可以在编译时选择Strategy,不需要在运行时改变,提高效率。
3)使Strategy对象称为可选
实际应用代码:
商场购物结账,根据不同的付账方式,选择不同的计算策略。CashContext用到了简单工厂,下面代码中策略模式与简单工厂相结合,降低了代码的耦合性。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyStrategy1
{
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;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyStrategy1
{
class 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);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyStrategy1
{
class Program
{
static void Main(string[] args)
{
double totalPrices = 100d;
string cashType = "打8折";
CashContext csuper = new CashContext(cashType);
totalPrices = csuper.GetResult(totalPrices);
Console.ReadKey();
}
}
}
参考《设计模式》、《大话设计模式》,进行整理。
本文深入探讨了策略模式的概念及其在编程中的应用。策略模式提供了一种封装算法并允许上下文根据需求选择不同算法的机制。通过实例代码演示了如何在不同场景下灵活使用策略模式,包括如何定义接口、实现具体策略类和上下文类,以及如何通过参数化策略类来动态改变算法。此外,文章还讨论了策略模式带来的好处,如消除条件语句、提高代码复用性和易于扩展性。
958

被折叠的 条评论
为什么被折叠?



