设计模式之-策略模式
定义:它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响到使用算法的客户。
策略模式是一种定义一系列算法的方法,从概念上来家看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有算法,减少了各种算法类于使用算法之间的耦合。
基本代码如下:
strategy类,定义所有支持的算法的公共接口
abstarct class Strategy { public abstract void AlgorithmInteface(); }
ConcreteStrategy,封装了具体的算法和行为,继承于Strategy
class ConcreteStrategyA: Strategy { public override void AlgorithmInterface() { Console.WriteLine("具体算法A的实现"); } } class ConcreteStrategyB : Strategy { public override void AlgorithmInterface() { Console.WriteLine("具体算法B的实现"); } } class ConcreteStrategyC : Strategy { public override void AlgorithmInterface() { Console.WriteLine("具体算法C的实现"); } }
Context类
class Context { Strategy strategy; public Context(Strategy strategy)//初始化时,传入具体的策略对象 { this.strategy = strategy;//注意:这是组合关系 } public void ContectInterface() { strategy.AlgorithmInterface();//根据具体的策略对象,调用起算法的方法 } }
客户端的调用
static void Main(string[] args) { Context context; context=new Context(new ConcreteStrategyA()); context.ContextUnterface(); context=new Context(new ConcreteStrategyB()); context.ContextUnterface(); context=new Context(new ConcreteStrategyC()); context.ContextUnterface(); }
上述策略模式的使用发现具体使用哪类算法的判断过程放在了客户端,可以使用简单工厂来改进策略模式
改造后的Context
class Context { Strategy sg = null; public Context(string abc) { switch (abc) { case "A": ConcreteStrategyA A = new ConcreteStrategyA(); sg = A; break; case "B": ConcreteStrategyB B = new ConcreteStrategyB(); sg = B; break; case "C": ConcreteStrategyC C = new ConcreteStrategyC(); sg = C; break; } } public void ContextInterface() { sg.AlgorithmInterface(); } }
再次改进,分别利用反射和配置文件的方式
class Context { Strategy sg = null; public Context(string abc) { //Assembly.Load("程序集名称").CreateInstance("当前类所在的名称空间." + 类名称); sg = (Strategy)Assembly.Load("ConsoleApp1").CreateInstance("ConsoleApp1." + abc); //反射 } public void ContextInterface() { sg.AlgorithmInterface(); } }
配置文件,添加引用Using System.Configuration,在App.config文件中加入如下:
<appSettings> <add key="DB" value="ConcreteStrategyA"/> </appSettings>
static void Main(string[] args)//客户端这样写 { string temp = ConfigurationManager.AppSettings["DB"]; Context context = new Context(temp); context.ContextInterface(); Console.ReadLine(); }
回顾:
策略模式是一种定义一系列算法的方法,从概念上来看所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有算法,减少了各种算法与使用算法类之间的耦合。
优点:
策略模式封装了变化【这个变化就是算法】
终结:
策略模式是用来封装算法的,但在实际的应用中,我们发现可以用它来封装几乎任何类型的规则。只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。
C++版本
#include<iostream> using namespace std; //抽象接口 class ReplaceAlgorithm { public: virtual void Replace() = 0; }; //三种具体的替换算法 class LRU_ReplaceAlgorithm : public ReplaceAlgorithm { public: void Replace() { cout << "Least Recently Used replace algorithm" << endl; } }; class FIFO_ReplaceAlgorithm : public ReplaceAlgorithm { public: void Replace() { cout << "First in First out replace algorithm" << endl; } }; class Random_ReplaceAlgorithm : public ReplaceAlgorithm { public: void Replace() { cout << "Random replace algorithm" << endl; } }; ///第一种方法:Cache需要用到替换算法 class Cache { private: ReplaceAlgorithm* m_ra; public: Cache(ReplaceAlgorithm* ra) { m_ra = ra; } ~Cache() { delete m_ra; } void Replace() { m_ra->Replace(); } }; /// <summary> /// 第二种用法,利用简单工厂进行优化了之后的 /// </summary> /// <returns></returns> /// //Cache需要用到替换算法 enum RA { LRU, FIFO, RANDOM }; //标签 class Cache0 { private: ReplaceAlgorithm* m_ra; public: Cache0(enum RA ra) { if (ra == LRU) m_ra = new LRU_ReplaceAlgorithm(); else if (ra == FIFO) m_ra = new FIFO_ReplaceAlgorithm(); else if (ra == RANDOM) m_ra = new Random_ReplaceAlgorithm(); else m_ra = NULL; } ~Cache0() { delete m_ra; } void Replace() { m_ra->Replace(); } }; /// <summary> /// 第三种方法 /// </summary> /// <returns></returns> /// //Cache需要用到替换算法 template <class RA> class Cache1 { private: RA m_ra; public: Cache1() { } ~Cache1() { } void Replace() { m_ra.Replace(); } }; int main() { //Cache cache(new LRU_ReplaceAlgorithm()); //暴露了算法的定义 //cache.Replace(); //Cache0 cache(LRU); //指定标签即可 //cache.Replace(); Cache1<Random_ReplaceAlgorithm> cache; //模板实参 cache.Replace(); return 0; }