设计模式之-策略模式
2011-07-25 22:16 java线程例子 阅读(247) 评论(0) 编辑 收藏 举报 *
* | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄| | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|
* | Context | | Strategy |
* |-----------------------------|◇-strategy---聚合------------→|-----------------------------|
* | Request | | Handle() |
* |________________| |________________|
* △
* |---------------|------------|
* | |
* | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄| | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|
* | ConcreateStrategyA | | ConcreateStrategyB |
* |---------------------------------- ----| |-----------------------------------|
* | Handle() | | Handle() |
* |_________________ ____| |___________________|
*
*
从上面UML图可以看出,从结构上来讲,策略模式跟桥模式很像,桥模式中抽象部分本身如果没有子类,那么桥模式就退化成了策略模式,相反如果策略模式中的Context类也可以独立演化,策略模式就进化成了桥模式。但从业务逻辑上来讲,这两个模式的应用目的是不一样的:桥模式侧重类本身和类行为实现部分各自独立发展,而策略模式则侧重不同算法的封装与支持。(其实很多模式之间的外观差异性很小,而且可以起到的作用也存在相似,这也是模式实际应用中很难区分到底是那个模式的原因)
采用策略模式的时候需要注意几点:一是策略算法的实现要相对独立,既不依赖或者少依赖策略调用者(本图中的Context 类;二是不同策略之间要相互独立,且能相互替代。这点很关键,如果不同的策略不能相互替代,就会造成调用者调用的不确定性(在这点上,桥模式不要求这点)。
另外如果策略算法依赖于调用者,则应该使用参数,而不要过多的暴露调用者本身的数据给策略类,因为暴露调用者的结构会造成策略类对调用者类的依赖,而相互依赖则增加了系统的耦合度。
策略类的创建和Contex类的创建可使用其它创建型模式来完成。
策略模式中的策略算法可能只是Context类中某个方法中的一个部分,在将策略算法中依赖的外界参数进行参数化后(由抽象策略提供标准的接口),策略算法就可以独立出来成为系统中的公共算法。
策略模式从某种意义上来见,侧重于算法,但实际上策略模式可以应用于各个方面,比较极端的例子是使用委托来实现算法策略,这种方式更为灵活,一个比较典型的例子就是排序函数的比较策略,一般情况下实现几种默认的比较算法,但因为比较策略算法实在是太多,则可以通过委托调用来让用户自己去实现。这种方式的扩展性和灵活性都比较好。C#的查询扩展方法基本都是采用这种方式实现。而匿名函数和兰姆达表达式的引入,也使得这种策略实现的方便性大大争强.
当然,利用委托充当策略抽象来实现策略算法最好用于那些多且不确定但算法简单的情况,对于算法复杂,算法比较固定的方式还是建议使用上述模式的标准方式。