`
wenlongsust
  • 浏览: 66723 次
  • 性别: Icon_minigender_1
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论

设计模式:桥接模式优点比较

阅读更多

原文链接:http://blog.csdn.net/jason0539/article/details/22568865

生活中的一个例子:
拿汽车在路上行驶的来说。既有小汽车又有公共汽车,它们都不但能在市区中的公路上行驶,也能在高速公路上行驶。这你会发现,对于交通工具(汽车)有不同的类型,它们所行驶的环境(路)也有不同类型,在软件系统中就要适应两个方面(不同车型,不同道路)的变化,怎样实现才能应对这种变化呢?

概述:
在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度?这就要使用Bridge模式。
意图:
   将抽象部分与实现部分分离,使它们都可以独立的变化。
——《设计模式》GOF

上面这些话我也没看懂。。太抽象了,但是一看代码你就明白是怎么回事了。
结构图:

传统的做法:
通过类继承的方式来做上面的例子;

先看一下类结构图:

代码实现:

  1. //基类路
  2. classRoad{
  3. voidrun(){
  4. System.out.println("路");
  5. }
  6. }
  7. //市区街道
  8. classStreetextendsRoad{
  9. voidrun(){
  10. System.out.println("市区街道");
  11. }
  12. }
  13. //高速公路
  14. classSpeedWayextendsRoad{
  15. voidrun(){
  16. System.out.println("高速公路");
  17. }
  18. }
  19. //小汽车在市区街道行驶
  20. classCarOnStreetextendsStreet{
  21. voidrun(){
  22. System.out.println("小汽车在市区街道行驶");
  23. }
  24. }
  25. //小汽车在高速公路行驶
  26. classCarOnSpeedWayextendsSpeedWay{
  27. voidrun(){
  28. System.out.println("小汽车在高速公路行驶");
  29. }
  30. }
  31. //公交车在市区街道行驶
  32. classBusOnStreetextendsStreet{
  33. voidrun(){
  34. System.out.println("公交车在市区街道行驶");
  35. }
  36. }
  37. //公交车在高速公路行驶
  38. classBusOnSpeedWayextendsSpeedWay{
  39. voidrun(){
  40. System.out.println("公交车在高速公路行驶");
  41. }
  42. }
  43. //测试
  44. publicstaticvoidmain(String[]args){
  45. //小汽车在高速公路行驶
  46. CarOnSpeedWaycarOnSpeedWay=newCarOnSpeedWay();
  47. carOnSpeedWay.run();
  48. //公交车在市区街道行驶
  49. BusOnStreetbusOnStreet=newBusOnStreet();
  50. busOnStreet.run();
  51. }

缺点:
但是我们说这样的设计是脆弱的,仔细分析就可以发现,它还是存在很多问题,首先它在遵循开放-封闭原则的同时,违背了类的单一职责原则,即一个类只有一个引起它变化的原因,而这里引起变化的原因却有两个,即路类型的变化和汽车类型的变化;其次是重复代码会很多,不同的汽车在不同的路上行驶也会有一部分的代码是相同的;

再次是类的结构过于复杂,继承关系太多,难于维护,最后最致命的一点是扩展性太差。如果变化沿着汽车的类型和不同的道路两个方向变化,我们会看到这个类的结构会迅速的变庞大。

应用设计模式
桥接模式(Bridge)来做;

先看一下类结构图:

代码实现:

  1. abstractclassAbstractRoad{
  2. AbstractCaraCar;
  3. voidrun(){};
  4. }
  5. abstractclassAbstractCar{
  6. voidrun(){};
  7. }
  8. classStreetextendsAbstractRoad{
  9. @Override
  10. voidrun(){
  11. //TODOAuto-generatedmethodstub
  12. super.run();
  13. aCar.run();
  14. System.out.println("在市区街道行驶");
  15. }
  16. }
  17. classSpeedWayextendsAbstractRoad{
  18. @Override
  19. voidrun(){
  20. //TODOAuto-generatedmethodstub
  21. super.run();
  22. aCar.run();
  23. System.out.println("在高速公路行驶");
  24. }
  25. }
  26. classCarextendsAbstractCar{
  27. @Override
  28. voidrun(){
  29. //TODOAuto-generatedmethodstub
  30. super.run();
  31. System.out.print("小汽车");
  32. }
  33. }
  34. classBusextendsAbstractCar{
  35. @Override
  36. voidrun(){
  37. //TODOAuto-generatedmethodstub
  38. super.run();
  39. System.out.print("公交车");
  40. }
  41. }
  42. publicstaticvoidmain(String[]args){
  43. AbstractRoadspeedWay=newSpeedWay();
  44. speedWay.aCar=newCar();
  45. speedWay.run();
  46. AbstractRoadstreet=newStreet();
  47. street.aCar=newBus();
  48. street.run();
  49. }

可以看到,通过对象组合的方式,Bridge 模式把两个角色之间的继承关系改为了耦合的关系,从而使这两者可以从容自若的各自独立的变化,这也是Bridge模式的本意。
这样增加了客户程序与路与汽车的耦合。其实这样的担心是没有必要的,因为这种耦合性是由于对象的创建所带来的,完全可以用创建型模式去解决。在应用时结合创建型设计模式来处理具体的问题。
应用设计模式:
桥接模式(Bridge)来做(
多维度变化);
结合上面的例子,增加一个维度"人",不同的人开着不同的汽车在不同的路上行驶(三个维度);
结合上面增加一个类"人",并重新调用.
代码实现:

  1. abstractclassPeople{
  2. AbstractRoadroad;
  3. voidrun(){}
  4. }
  5. classManextendsPeople{
  6. @Override
  7. voidrun(){
  8. //TODOAuto-generatedmethodstub
  9. super.run();
  10. System.out.print("男人开着");
  11. road.run();
  12. }
  13. }
  14. classWomanextendsPeople{
  15. @Override
  16. voidrun(){
  17. //TODOAuto-generatedmethodstub
  18. super.run();
  19. System.out.print("女人开着");
  20. road.run();
  21. }
  22. }
  23. publicstaticvoidmain(String[]args){
  24. AbstractRoadspeedWay=newSpeedWay();
  25. speedWay.aCar=newCar();
  26. Peopleman=newMan();
  27. man.road=speedWay;
  28. man.run();
  29. }


效果及实现要点:
1.Bridge模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。
2.所谓抽象和实现沿着各自维度的变化,即“子类化”它们,得到各个子类之后,便可以任意它们,从而获得不同路上的不同汽车。
3.Bridge模式有时候类似于多继承方案,但是多继承方案往往违背了类的单一职责原则(即一个类只有一个变化的原因),复用性比较差。Bridge模式是比多继承方案更好的解决方法。
4.Bridge模式的应用一般在“两个非常强的变化维度”,有时候即使有两个变化的维度,但是某个方向的变化维度并不剧烈——换言之两个变化不会导致纵横交错的结果,并不一定要使用Bridge模式。

适用性:
在以下的情况下应当使用桥梁模式:
1.如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的联系。
2.设计要求实现化角色的任何改变不应当影响客户端,或者说实现化角色的改变对客户端是完全透明的。
3.一个构件有多于一个的抽象化角色和实现化角色,系统需要它们之间进行动态耦合。
4.虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者。


总结:
Bridge模式是一个非常有用的模式,也非常复杂,它很好的符合了开放-封闭原则和优先使用对象,而不是继承这两个面向对象原则。




小龙评论


通过桥接模式是否使用的比较,优点很明显。这样,可以更加容易地理解桥接模式的内涵。

另外,该博主写的设计模式专栏http://blog.csdn.net/column/details/jason0539-shejimoshi.html,的确都很不错,力荐!


分享到:
评论

相关推荐

    设计模式之原型模式和桥接模式摘录

    Prototype:(1)、意图:用原型实例...(3)、优点:A、运行时刻增加和删除产品:Prototype允许只通过客户注册原型实例就可以将一个新的具体产品类并入系统。它比其他创建型模式更为灵活,因为客户可以在运行时刻建立和

    design-pattern-forjava.zip

    design-pattern-forjava 基于java版的设计模式实现。 1,抽象工厂模式,提供一个创建一系列相关或互相依赖对象的接口,而无需指定他们具体的类. 2,适配器模式:将一个类的接口转换成客户希望的另外一个接口.Adapter...

    APA2068_datasheet.pdf

    为了简化音频系统设计, APA2068结合了立体声桥接式负载( BTL )模式的扬声器驱动器和立体声单端( SE)模式,耳机驱动器插入一个芯片上,其中两个模式是容易地切换由SE / BTL输入控制引脚的信号

    学生信息管理系统java课程设计报告.doc

    本课程设计 研究了一种基于数据关联规则的网络学生信息管理系统,此方案与现今网上已采用的一 些方案相比,具有用户使用更简单、界面更直观等优点。 在设计中我们发现这样一个事实,一个用户或管理员在登陆这个网站...

    软件框架设计的艺术

    2.5 开发第一个版本通常比较容易 24 第3章 评价API好坏的标准 26 3.1 方法和字段签名 26 3.2 文件及其内容 27 3.3 环境变量和命令行选项 29 3.4 文本信息也是API 30 3.5 协议 32 3.6 行为 35...

    千兆以太网技术与应用

    1.1.3 1983-1997:LAN桥接与交换 2 1.1.4 1992-1997:快速以太网 2 1.1.5 1996—今:千兆以太网 3 1.2 以太网流行的原因 3 1.2.1 以太网与令牌环 3 1.2.2 价格取胜 4 1.2.3 DIX贡献出他们唯一的LAN,以太 网...... ...

    Cisco路由器手册

    1.1 优点 1 1.2 软件包 3 1.3 所支持的特性 4 1.3.1 协议 4 1.3.2 管理 8 1.3.3 多媒体和QoS 8 1.3.4 安全数据传送 8 1.3.5 对IBM网络环境的支持 9 1.3.6 IP路由协议 9 1.3.7 桥接 10 1.3.8 报文交换 10 1.3.9 ...

    如何实现软件无线电台的组网方案设计

    它具有多频段、多模式等优点,克服了现有军用电台的单信道、单模式、互通差、协同难等缺点。目前,软件无线电台主要用于不同电台或电台网络间起桥接或网关作用。随着应用的不断扩大,考虑其作为网络中的基本节点时的...

    基于状态机的PEX8311的DMA实现

    结合PCI-Express的传输特性,分析了PEX8311的DMA传输模式与时序逻辑,通过有限状态机的设计,实现PEX8311的DMA传输。与其他设计相比,利用有限状态机理论设计控制逻辑具有直观、简单、设计流程短等优点,并对状态机...

Global site tag (gtag.js) - Google Analytics