策略模式(Strategy):他定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响到使用算法 的客户。
//策略类,定义所有支持的算法的公共接口
abstract class Strategy
{
public abstract void Algorithmlnterface();
}
//具体策略类,封装了具体的算法或行为。下同
class ConcreteStrategyA:Strategy
{
public override void Algorithmlnterface()
{
Console.WriteLine("算法A");
}
}
class ConcreteStrategyB:Strategy
{
public override void Algorithmlnterface()
{
Console.WriteLine("算法B");
}
}
class ConcreteStrategyC : Strategy
{
public override void Algorithmlnterface()
{
Console.WriteLine("算法C");
}
}
//Context上下文,用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用。
class MyContext
{
Strategy stra;
//初始化时传入具体的策略对象
public MyContext(Strategy strategy)
{
this.stra = strategy;
}
//根据具体的策略对象,调用器算法的方法。
public void ContectInterface()
{
stra.Algorithmlnterface();
}
}
调用
MyContext con;
con = new MyContext(new ConcreteStrategyA());
con.ContectInterface();
con = new MyContext(new ConcreteStrategyB());
con.ContectInterface();
con = new MyContext(new ConcreteStrategyC());
con.ContectInterface();
下面修改代码,不再客户端判断用哪个算法:
//Context上下文,用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用。
class MyContext
{
//将实列化具体策略的过程由客户端转移到Context类中,简单工厂的应用
Strategy strat = null;
//初始化时传入字符串
public MyContext(string str)
{
switch(str)
{
case "算法A":
ConcreteStrategyA strA = new ConcreteStrategyA();
strat = strA;
break;
case "算法B":
ConcreteStrategyB strB = new ConcreteStrategyB();
strat = strB;
break;
case "算法C":
ConcreteStrategyC strC = new ConcreteStrategyC();
strat = strC;
break;
}
}
//根据具体的策略对象,调用器算法的方法。
public void ContectInterface()
{
strat.Algorithmlnterface();
}
}
调用
MyContext con;
//简单工厂调用
con = new MyContext("算法A");
con.ContectInterface();
//直接策略调用
//con = new MyContext(new ConcreteStrategyA());
//con.ContectInterface();
工厂凡是switch...case..都可以考虑考虑反射:
using System.Reflection;//要引用这个
class MyContext
{
public MyContext(string str)
{
}
private static readonly string AssemblyName = "MyStratery";
private static readonly string db = "A";
public static Strategy CreatorStrategy()
{
//这里注意有可能程序集名称并不是命名空间,我没改默认是一样的。
string classname = AssemblyName + ".ConcreteStrategy" + db;
return (Strategy)Assembly.Load(AssemblyName).CreateInstance(classname);
}
public void ContectInterface()
{
strat.Algorithmlnterface();
}
}
//客户端调用
Strategy strat;
//MyContext con;
//con = new MyContext(new ConcreteStrategyA());
//con.ContectInterface();
// con = new MyContext("算法A");
//con.ContectInterface();
strat = MyContext.CreatorStrategy();
strat.Algorithmlnterface();
总结一下:当不同的行为堆砌在一个类中时,就很难避免使用条件语句来选择合适的行为。将这些行为封装在一个个独立的Strategy类中,可以在使用这些行为的类中消除条件语句。
策略模式是用来封装算法的,但在实践中,我们发现可以用他来封装几乎任何类型的规则,只要在分析过程中听到需要不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。