strategy模式与 bridge模式的区别

实际上所有模式可以只分为类模式和对象模式两种,类模式是用继承而对象模式是用委托   


Bridge模式和Strategy模式相似就是因为他们都将任务委托给了另外一个接口的具体实现 ,   
他们之间的区别在于Bridge的目的是让底层实现和上层接口可以分别演化,从而提高移植性   
而Strategy的目的是将复杂的算法封装起来,从而便于替换不同的算法。   
因此可以想象一般情况下Bridge的实现几乎不会在运行时更改而Strategy的算法则很有可能   
需要在运行时更换,这就导致在细节方面需要考虑的因素可能会很不相同。

strategy模式是为了扩展和修改,并提供动态配置。它往往可以在同一环境当中使用不同的策略,就是调用不同的派生类。其内部实现是自由的,不受已有的类接口的限制(很多时候根本就不调用现成的接口)。   
bridge模式是往往是为了利用已有的方法或类。它将原来不统一,不兼容的接口封装起来,变成统一的接口。它的应用往往是不同的环境或平台下只能选择一 种,比如说在windows平台下只能用WinClass,而在unix平台下只能用UnixClass.它的主要作用不是配置而是定义通用接口。   
据个例子来说:我要画园,要实心园,我可以用SolidPen来配置,画虚线园可以用dashedPen来配置。这是strategy模式。   
而同样是画园,我是在windows下来画实心园,就用windowPen+solidPen来配置,在unix下画实心园就用 unixPen+solidPen来配置。如果要再windows下画虚线园,就用windowsPen+dashedPen来配置,要在unix下画虚 线园,就用unixPen+dashedPen来配置。   
我这里仅仅是就一种情况来说strategy和bridge的组合应用,其他的组合可能性随环境变化而多种多样。从中可以看出,bridge和strategy是可能组合使用,侧重不同方面的。   
模式某种角度上来讲就是对象组合。不要看他们都是对象组合就好像是一样的。模式的动机,意图,使用场合,组合方式,这些都是模式的一部分。其中细微的不同足以区分不同的模式。

桥接(Bridge)模式是结构型模式的一种,而策略(strategy)模式则属于行为模式 。以下是它们的UML结构图。

在桥接模式中,Abstraction通过聚合的方式引用Implementor。

从桥接模式与策略模式谈起 - 一半是火焰,一半是海水 - BlogJava - silence - 守望者

在策略模式中,Context也使用聚合的方式引用Startegy抽象接口。

从桥接模式与策略模式谈起 - 一半是火焰,一半是海水 - BlogJava - silence - 守望者

从他们的结构图可知,在这两种模式中,都存在一个对象使用聚合的方式引用另一个对象的抽象接口的情况,而且该抽象接口的实现可以有多种并且可以替换。可以说两者在表象上都是调用者与被调用者之间的解耦,以及抽象接口与实现的分离。

那么两者的区别体现在什么地方呢?

1. 首先,在形式上,两者还是有一定区别的,对比两幅结构图,我们可以发现,在桥接模式中不仅Implementor具有变化 (ConcreateImplementior),而且Abstraction也可以发生变化(RefinedAbstraction),而且两者的变化 是完全独立的,RefinedAbstraction与ConcreateImplementior之间松散耦合,它们仅仅通过Abstraction与 Implementor之间的关系联系起来。而在策略模式中,并不考虑Context的变化,只有算法的可替代性。

2. 其次在语意上,桥接模式强调Implementor接口仅提供基本操作,而Abstraction则基于这些基本操作定义更高层次的操作。而策略模式强调 Strategy抽象接口的提供的是一种算法,一般是无状态、无数据的,而Context则简单调用这些算法完成其操作。

3. 桥接模式中不仅定义Implementor的接口而且定义Abstraction的接口,Abstraction的接口不仅仅是为了与 Implementor通信而存在的,这也反映了结构型模式的特点:通过继承、聚合的方式组合类和对象以形成更大的结构。在策略模式中,Startegy 和Context的接口都是两者之间的协作接口,并不涉及到其它的功能接口,所以它是行为模式的一种。行为模式的主要特点就是处理的是对象之间的通信方 式,往往是通过引入中介者对象将通信双方解耦 ,在这里实际上就是将Context与实际的算法提供者解耦。

所以相对策略模式,桥接模式要表达的内容要更多,结构也更加复杂。桥接模式表达的主要意义其实是接口隔离的原则,即把本质上并不内聚的两种体系区别 开来,使得它们可以松散的组合,而策略在解耦上还仅仅是某一个算法的层次,没有到体系这一层次。从结构图中可以看到,策略的结构是包容在桥接结构中的,桥 接中必然存在着策略模式,Abstraction与Implementor之间就可以认为是策略模式,但是桥接模式一般Implementor将提供一系 列的成体系的操作,而且Implementor是具有状态和数据的静态结构。而且桥接模式Abstraction也可以独立变化。

Bridge  例子: Bridge遵循的是接口隔离原则的典型。如  JDBC , 我们都知道JDBC是使用Bridge模式进行设计的,DriverManager就是其中的Abstraction,java.sql.Driver是Implementor,com.mysql.jdbc.Driver是Implementor的一个具体实现(请参考GOF的Bridge模式的描述)。大家注意了,前一个Driver是一个接口,后者却是一个类,它实现了前面的Driver接口。

strategy:

  以一个算术运算为例,传统做法为:

java 代码
  1. package  org.common;   
  2.   
  3. public   class  Calculate {   
  4.        
  5.      public  String getResult( float  a, float  b, char  c){   
  6.            
  7.          float  add = a+b;   
  8.          float  sub = a-b;   
  9.          float  mult = a*b;   
  10.          float  division = a/b;   
  11.            
  12.          switch (c){   
  13.              case  '+':   
  14.                  return   "相加结果为:"  + add;   
  15.              case  '-':   
  16.                  return   "相减结果为:"  + sub;   
  17.              case  '*':   
  18.                  return   "相乘结果为:"  + mult;   
  19.              case  '/':   
  20.                  return   "相除结果为:"  + division;   
  21.              default :   
  22.                  return   "出错" ;   
  23.         }   
  24.     }   
  25.   
  26. }  

 

java 代码
  1. package  org.common;   
  2.   
  3. public   class  Test {   
  4.        
  5.      public   static   void  main(String[] args){   
  6.          float  a =  200 ;   
  7.          float  b =  50 ;   
  8.         Calculate cal =  new  Calculate();   
  9.         System.out.println(cal.getResult(a, b, '+'));   
  10.         System.out.println(cal.getResult(a, b, '-'));   
  11.         System.out.println(cal.getResult(a, b, '*'));   
  12.         System.out.println(cal.getResult(a, b, '/'));   
  13.         System.out.println(cal.getResult(a, b, '('));   
  14.     }   
  15.   
  16. }   

 

运行结果为:

 相加结果为:250.0
相减结果为:150.0
相乘结果为:10000.0
相除结果为:4.0
出错

2. 用策略模式来实现:

策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。
策略模式使得算法可以在不影响到客户端的情况下发生变化。使用策略模式可以把行为和环境分割开来。
环境类负责维持和查询行为类,各种算法则在具体策略中提供。由于算法和环境独立开来,算法的修改都不会影响环境和客户端

策略模式:

由三部分组成

A:   抽象策略角色:策略类,通常由一个接口或者抽象类实现
B:  具体策略角色:包装了相关的算法和行为
C:  环境角色:持有一个策略类的引用,最终给客户端调用的。

一个抽象策略角色:

java 代码
  1. package  org.strategy;   
  2. /**   
  3.  * 抽象策略角色   
  4.  */   
  5. public   abstract   class  AbstractStrategy {   
  6.   
  7.      public   abstract  String calculate( float  a, float  b);   
  8. }   

几个具体策略角色:

java 代码
  1. package  org.strategy;   
  2. /**   
  3.  * 具体策略角色   
  4.  */   
  5. public   class  SubStrategy  extends  AbstractStrategy{   
  6.   
  7.      public   String calculate( float  a, float  b){   
  8.          float  result = a-b;   
  9.          return   "相减结果为:"  + result;   
  10.     }   
  11. }  

 

java 代码
  1. package  org.strategy;   
  2. /**   
  3.  * 具体策略角色   
  4.  */   
  5. public   class  AddStrategy  extends  AbstractStrategy{   
  6.   
  7.      public   String calculate( float  a, float  b){   
  8.          float  result = a+b;   
  9.          return   "相加结果为:"  + result;   
  10.     }   
  11. }   

 

java 代码
  1. package  org.strategy;   
  2. /**   
  3.  * 具体策略角色   
  4.  */   
  5. public   class  MultStrategy  extends  AbstractStrategy{   
  6.   
  7.      public   String calculate( float  a, float  b){   
  8.          float  result = a*b;   
  9.          return   "相乘结果为:"  + result;   
  10.     }   
  11. }  

 

 

java 代码
  1. package  org.strategy;   
  2. /**   
  3.  * 具体策略角色   
  4.  */   
  5. public   class  DivisionStrategy  extends  AbstractStrategy{   
  6.   
  7.      public   String calculate( float  a, float  b){   
  8.          float  result = a/b;   
  9.          return   "相除结果为:"  + result;   
  10.     }   
  11. }   

环境角色:

java 代码
  1. package  org.strategy;   
  2. /**   
  3.  * 环境角色,最终给客户端调用的   
  4.  */   
  5. public   class  ContextRole {   
  6.   
  7.      /**   
  8.      * 拥有一个策略类的引用   
  9.      */   
  10.      private  AbstractStrategy abstactStrategy;   
  11.        
  12.      public  ContextRole(AbstractStrategy abstactStrategy){   
  13.          this .abstactStrategy = abstactStrategy;   
  14.     }   
  15.        
  16.      public  String calculate( float  a, float  b) {   
  17.         String result = abstactStrategy.calculate(a, b);   
  18.          return  result;   
  19.     }   
  20. }  

客户端调用:

java 代码
  1. package  org.strategy;   
  2. /**   
  3.  * 客户端   
  4.  */   
  5. public   class  Test {   
  6.        
  7.      public   static   void  main(String[] args){   
  8.          float  a =  200 ;   
  9.          float  b =  25 ;   
  10.            
  11.         ContextRole contextRole1 =  new  ContextRole( new  AddStrategy());   
  12.         System.out.println(contextRole1.calculate(a, b));   
  13.            
  14.         ContextRole contextRole2 =  new  ContextRole( new  SubStrategy());   
  15.         System.out.println(contextRole2.calculate(a, b));   
  16.            
  17.         ContextRole contextRole3 =  new  ContextRole( new  MultStrategy());   
  18.         System.out.println(contextRole3.calculate(a, b));   
  19.            
  20.         ContextRole contextRole4 =  new  ContextRole( new  DivisionStrategy());   
  21.         System.out.println(contextRole4.calculate(a, b));   
  22.            
  23.     }   
  24.   
  25. }   

 

输出结果为:

相加结果为:225.0
相减结果为:175.0
相乘结果为:5000.0
相除结果为:8.0

总结:

策略模式优点:

1.可以很方便的动态改变算法或行为

2.避免使用多重条件转移语句

策略模式缺点:


1.客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
2.造成很多的策略类。

 

说明:本文转自不同的出处,请作者见谅

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值