浑浑噩噩的过的漫无目的,更多的是迷茫,真不知该如何定位自己的人生?空有远大抱负,而又力不从心!有句话说的好,当你的才能撑不起你的野心的时候,就该静下来心来好好学习了!于是闲来无事,便继续开始我的设计模式之游!今天便研究下策略者模式!
1、策略者模式解析
大话设计模式是这样讲道:
策略者模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法减少各种算法类与使用算法类之间的耦合[DPE]。
个人理解:所谓一系列算法方法就是一系列的类,即每个算法对应一个类;它可以以相同的方式调用所有的算法,这个也就是多态的应用(统一调用不同实现)。那么如何才能做到统一调用不同实现呢,那么我们第一个想到的便是会有父类,子类;废话少说直接代码贴上!
2、策略者模式实例
场景:随便定义两个数,根据不同的符号进行计算结果!
2.1策略模式的组成
抽象策略角色 :策略类,通常由一个接口或者抽象类实现
具体策略角色 :包装了相关的算法和行为,继承抽象策略角色
配置角色 :既有策略类的引用,最终给客户端调用的。
//算法抽象类 abstract class Strategy { public abstract int CalculationInterface(int num1,int num2); } class Add:Strategy { public override int CalculationInterface(int num1,int num2) { return num1+num2; } } class Subtraction :Strategy { public override int CalculationInterface(int num1,int num2) { return num1-num2; } }
简单工厂实现:
//简单工厂实现 class CalculationFactory { public static Strategy CreateCalculationInterface(string type) { Strategy sy=null; switch (type)//根据不同类型实例化不同算法类 { case "+": sy=new Add();break; case "-": sy=new Subtraction();break; } return sy; } } static void Main(string[] args) { int num1=10,num2=6; Strategy strategy=CalculationFactory.CreateCalculationInterface("+"); Console.WriteLine(strategy.CalculationInterface( num1, num2)); strategy=CalculationFactory.CreateCalculationInterface("-"); Console.WriteLine(strategy.CalculationInterface( num1, num2)); Console.ReadLine(); }
解析:
我们只需要传递相应的条件就能得到想要的一个对象,然后通过这个对象实现算法的操作!
策略模式实现:
//策略模式实现 //创建一个类用来配置对Strategy对象的引用 class Context { Strategy strategy; public Context(Strategy strategy)//初始化时,传入具体的策略对象 { this.strategy=strategy; } //上下文接口 public int GetResult(int num1,int num2) { return strategy.CalculationInterface( num1, num2);//根据具体的策略对象调用其算法 } } static void Main(string[] args) { int num1=10,num2=6; Context context; switch (type)//根据不同类型实例化不同算法类 { case "+": context=new Context(new Add());break; case "-": context=new Context(new Subtraction());break; } Console.WriteLine(context.GetResult( num1, num2)); Console.ReadLine(); }
解析:
使用时必须首先创建一个想使用的类对象,然后将该对象最为参数传递进去,通过该对象调用不同的算法;
但是还是有不足之处:判断过程又跑到了客户端,但是我们该如何把判断过程从客户端转移走呢?那就把工厂与策略模式结合。
工厂结合策略模式实现:
//策略模式与简单工厂的结合; Class Context { Strategy _startrgy=null; public Context(string type)//此时不是具体的策略对象而是字符串 { switch (type)//根据不同类型实例化不同算法类 { case "+": _startrgy=new Add();break; case "-": _startrgy=new Subtraction();break; } } public int GetResult(int num1,int num2) { return _startrgy.CalculationInterface( num1, num2); } } static void Main(string[] args) { int num1=10,num2=6; Context context=new Context("+"); Console.WriteLine(context.GetResult( num1, num2)); //实例化不同的策略获得不同的结果 context=new Context("-"); Console.WriteLine(context.GetResult( num1, num2)); Console.ReadLine(); }
2、简单工厂与简单工厂结合策略模式比较
//简单工厂 Strategy strategy=CalculationFactory.CreateCalculationInterface("+"); ...=strategy.CalculationInterface(...); //策略模式与简单工厂结合 Context context=new Context("+"); ...=context.GetResult(...);
解析:
简单工厂需要客户端认识两个类:Strategy和CalculationFactory;而策略模式与简单工厂结合只需要客户端认识一个类:Context就可以了,从而降低了耦合度;
总结:
优点:
1、每个算法都是单独的类,简化了单元测试,可以通过自己的接口单独测试[DPE];
2、策略模式是一种定义一系列算法的方法,它可以以相同方式调用不同算法,减少了各种算法类与使用算法类之间的耦合;
缺点:
1、客户端需要理解所有具体策略类之间的区别,以便选择合适的算法,在一定程度上增加了客户端的使用难度;
2、每种算法都是一个策略类会造成很多的策略类,导致系统庞大难以维护;
遗留问题:
无论是简单工厂还是简单工厂与策略模式两者的结合,始终都存在一个问题:用到了switch,也就是说如果我们需要增加一种算法,必须要去更改Context中的switch代码,这总还是让人不爽的!
当然还是有办法去解决的,具体解决方案后续讨论!
今天的策略模式就写到此,希望各位博友们多多指教!