浅谈设计模式(Bridge pattern和 Strategy pattern)

  这段时间做项目,需要用到多种设计模式的结合,之前菜菜本人只用过简单工厂和单态模式,于是又抓紧多学了些,以下,菜菜将就Bridge pattern和Strategy pattern两者的比较,来一起学习一下这两个模式。

在具体给出两者具体异同点、优缺点之前,给出一下文档给的定义:

桥接模式:一种结构模式(牛郎织女本在一起,将牛郎和织女分开,中间搭一座桥)

策略模式:一种行为模式(将各种算法封装,用户可随意挑选需要的算法)

下面分开讲解,我们先来看一下Bridge模式的模型:

从UML图中,可以很容易看出桥接模式的参与者主要有:

抽象类,扩充抽象类,实现类,具体实现类。 具体每个参与对象的概念在这里就不详细解决,不理解的童鞋可以去百度一下,很多,主要说一下这几个参与对象在Bridge模式中是如何进行协调工作,达到什么样的功效,稍后给出各部分代码。

在Bridge模式中,要理解“桥接”这个概念,在上面描述的四个参与者中,从字面可以看出分为抽象部分和实现部分,那么桥接的发生,自然是发生在这两者之间,即桥接抽象部分与实现部分。起桥接作用的是扩充抽象类,而且,大家记住了,在桥接模式中,桥接是“单向桥”,即只能由抽象部分的对象去使用具体实现部分的对象。

桥接模式的意图:使得抽象和实现部分都能独立变化,达到可扩充性。可以理解为,抽象部分和实现部分其实是在某种程度上是独立的,只不过抽象部分用了实现部分对外的接口而已。

好了,假设有这么一个案例,菜菜想请人陪自己娱乐,如果是猫猫来了要看电影呢,他俩就去影院;如果是公猫来了要吃大餐呢,他俩就去西餐厅,用桥接模式,就这样实现:

抽象类:

Code:
  1. /* 
  2.  * 抽象部分Abstraction 
  3.  */  
  4. public abstract class EngagedAbstraction {  
  5. public abstract void getReady(Plan plan);  
  6. }  

扩充抽象类:

Code:
  1. /* 
  2.  * 抽象实现部分(扩充抽象) 
  3.  */  
  4. public class Caicai extends EngagedAbstraction{  
  5.   
  6. public void getReady(Plan paln) {  
  7.     // TODO Auto-generated method stub  
  8.       System.out.print("菜菜同"+paln.getName());  
  9.      if(paln.getplanName().equals( "eat")) {  
  10.       
  11.          System.out.println("去西餐厅"+paln.getplanName());  
  12.           
  13.      }  
  14.      else  
  15.         System.out.println("去影院"+paln.getplanName());  
  16.           
  17.     }  
  18.         
  19. }  

实现类接口(在这里菜菜就还是用抽象类写了,用Interface一样的)

Code:
  1. /* 
  2.  * 实现类接口 
  3.  */  
  4. public abstract class Plan {  
  5.       
  6.      // 很少用JAVA的get与Set方法,试一下,大家也可以直接用变量测试和熟悉该模式  
  7.        
  8.      protected String name;  
  9.        
  10.      public void setName(String name){  
  11.       this.name = name;  
  12.      }  
  13.      public String getName(){  
  14.       return this.name;  
  15.      }  
  16.        
  17.      protected String planName;  
  18.        
  19.      public void setplanName(String name){  
  20.       this.planName = name;  
  21.      }  
  22.      public String getplanName(){  
  23.       return this.planName;  
  24.      }  
  25.        
  26. public abstract void bringUp(String planName);  
  27.    
  28. }  

具体实现类(就是实现类接口的实现,有点绕口)

Code:
  1. /* 
  2.  * 具体实现类 
  3.  */  
  4. public class Mao extends Plan {  
  5.   
  6.       
  7.     public void bringUp(String planName) {  
  8.         // TODO Auto-generated method stub  
  9.         setplanName(planName);  
  10.     }  
  11.   
  12.       
  13.     public String getName() {  
  14.         // TODO Auto-generated method stub  
  15.         return super.getName();  
  16.     }  
  17.   
  18.       
  19.     public String getplanName() {  
  20.         // TODO Auto-generated method stub  
  21.         return super.getplanName();  
  22.     }  
  23.   
  24.       
  25.     public void setName(String name) {  
  26.         // TODO Auto-generated method stub  
  27.         super.setName(name);  
  28.     }  
  29.   
  30.       
  31.     public void setplanName(String name) {  
  32.         // TODO Auto-generated method stub  
  33.         super.setplanName(name);  
  34.     }  
  35.   
  36.   
  37.    
  38. }  

下面就是客户端测试类:

Code:
  1. /* 
  2.  * 客户端测试类 
  3.  */  
  4. public class Client {  
  5.       
  6. public static void main(String[] args)  
  7. {  
  8.    Plan gongMao=new Mao();  
  9.    gongMao.setName("公猫");  
  10.    gongMao.bringUp("eat");  
  11.      
  12.    Plan muMao=new Mao();  
  13.    muMao.setName("猫");  
  14.    muMao.bringUp("watch film");  
  15.      
  16.    Caicai man=new Caicai();  
  17.    man.getReady(gongMao);  
  18.    man.getReady(muMao);  
  19. }  
  20. }  

运行结果:

Code:
  1. 菜菜同公猫去西餐厅eat  
  2. 菜菜同猫去影院watch film  

为什么需要这么设计呢? 现在设想一种情况,菜菜找人娱乐的方式多了,不只是影院和西餐厅,还想去步行街。 而猫的伙伴多了,来了大脸猫,它还想要要逛街(或者菜菜想陪公猫去影院,和猫去西餐厅喝酒),就是说,抽象部分和实现部分都需要发生变化(其实这两者可以独立变化,不对对方产生影响),那么用上面的桥接模式,就很简单了,哪部分需求变了就改哪一部分,客户端根本不知道,即保证了扩充性,又保证了对客户的透明性。

理解了吗,各位,下面让我们看看Strategy(策略模式),说简单一点,策略模式在形式上,或者说在代码结构上,少了那个桥接部分(也就是扩充抽象类)。当然了,这样一个说法,是让大家先提前在脑子里面有个策略模式的大体UML模型。

 

直接上代码啦:

策略的接口(或者抽象类)

Code:
  1. //抽象的策略角色(也可以是接口,和Bridge模式同理)  
  2. public abstract class Caicai {  
  3.  public abstract void operate();  
  4. }  

策略的实现(只写了两个策略,一个去影院,一个去餐厅)

Code:
  1. /* 
  2.  * 策略的实现,去影院的策略 
  3.  */  
  4. public class Cinema extends Caicai{  
  5.  public void operate(){  
  6.   System.out.println("菜菜和公猫去影院");  
  7.  }  
  8. }  
Code:
  1. /* 
  2.  * 策略的实现,去餐厅的策略 
  3.  */  
  4. public class Resturant extends Caicai{  
  5.  public void operate(){  
  6.   System.out.println("菜菜和猫去餐厅");  
  7.  }  
  8. }  

上下文(Context)

Code:
  1. /* 
  2.  * 上下文 
  3.  */  
  4. public class Context {  
  5.       
  6.     private Caicai strategy;     
  7.     //构造函数,选择哪一个策略     
  8.     public Context(Caicai strategy){     
  9.         this.strategy = strategy;     
  10.     }     
  11.          
  12.     public void operate(){     
  13.         this.strategy.operate();     
  14.     }     
  15.   
  16. }  

客户端程序

Code:
  1. /* 
  2.  * 客户端程序 
  3.  */  
  4. public class Client {  
  5.  public static void main(String[] args) {  
  6.   Context context;  
  7.   context=new Context(new Resturant());  
  8.   context.operate();  
  9.   context=new Context(new Cinema());  
  10.   context.operate();  
  11.  }  
  12. }  

运行结果

Code:
  1. 菜菜和猫去餐厅  
  2. 菜菜和公猫去影院  

 

OK,代码完成了,写的虽然是最简单的策略模式,但是相信也是最容易让大家理解的。 和桥接模式从代码结构看,少了扩充抽象类,把抽象类改成了上下文(Context),即策略的决定者。

看完代码,经过菜菜粗略的介绍,相信大家在心里对策略模式有了一点点了解了吧,下面,再啰嗦一下策略模式的定义,到最后再比较它和桥接模式。

策略模式:又称为算法簇模式。从以上代码的策略实现类,可以看出,每一个实现类都封装了一种变化。于是,采用策略模式可以根据用户不同配置,选择相应的算法,可以避免条件语句带来的代码混乱,提高代码的可读性和程序的灵活性。

现在菜菜和大家一起学习了一遍bridge和strategy两个模式(在写文章的时候才忘记策略模式的demo忘写了,刚补起来呢),那么它们各自有哪些优缺点呢? 在这里,菜菜把自己查到的一些资料上讲述的,和大家分享一下,大家有什么更好的想法或者资料,欢迎交流。

优点和相同点:都很好的体现了面向对象的思想(封装变化),体现了设计模式的精髓(替代继承关系),都在某种程度上体现了独立性(可扩展性),都是 环境(上下文)/扩充抽象类  来决定策略/具体实现

缺点和不同点:策略模式的客户端需要知道所有策略类,才能选择;策略模式可能会出现很多策略类,导致程序的臃肿

                            桥接模式和策略模式的主要差别是目的不一样,策略模式的目的是封装算法,使得算法可以相互替换;而桥接的目的是分离抽象与实现,使抽象和实现可以独立变化。

好啦,真累,讲完了,自己又有一种不知所云的感觉了,希望不要把本来已经理解的同志给搞迷糊了。 策略模式讲的少一点,因为是今天下午才看的,嘿嘿,见谅哇。。   尽情拍砖。

 

 

 

 

评论 27
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值