桥接模式

桥接模式要把握的很重要的一点就是:类的继承关系和类的组合/聚合关系,何时应该考虑使用何种关系。是不是在编程过程中一味地使用类的继承关系就代表这就是面向对象编程了?有时候并不是这样,Java的类继承设计成单继承模式我想应该就是不想把类的继承关系搞得过于复杂,实际上我们应该优先使用对象组合/聚合,而不是类继承。类继承不必我们多说,我们来看看何为组合/聚合关系。

当我们看到上图过后应该能明白什么是组合和聚合了。聚合体现的是“弱”的拥有关系,比如雁群可以包含大雁,但雁群不是大雁的一部分。组合体现的是“强”的拥有关系,或者体现的是部分与整体的关系,通过一对翅膀组合成大雁,翅膀是部分,大雁是整体。

在了解了什么是组合/聚合过后,我们来看看什么是桥接模式。同样我们通过《大话设计模式》书中的例子来说明。

在N多年前手机还未像现在的手机市场一样,由Android和iOS一统天下。N年前各个手机厂商的软件几乎是互不兼容,更严重的可能是同一个手机厂商不同型号的手机也互不兼容。如果我们考虑这种场景应该如何来设计我们的代码呢?我们通过手机品牌来分类。

这就是我们通过类继承造成的结果。如果现在需要新增一个手机品牌S的话,就得再增加手机品牌S的下属功能子类,手机品牌千千万万那要增加的类就不计其数。我们再换一种通过软件分类来呢?

其实这不也一样吗?其实质还是通过类的继承来实现。新增一个功能过后同样要新增N个手机品牌对应的软件。从上面两种设计中,其实我们可以发现可以将“手机”这个抽象的概念将其剥离为“手机软件”和“手机品牌”这两个实现,具体是怎么做到的呢?我们来看桥接模式下的UML类结构图。

通过UML类结构图我们可以看到手机品牌和手机软件成功解耦,新增功能并不影响其手机品牌,新增手机品牌也不会影响到手机软件,其中的奥秘就在于利用了聚合而不是继承。(但其实,我觉得在这个地方所举的这个例子有失偏颇。从开始我们假定的场景是各个手机品牌互不兼容各自的手机软件,最开始两种“坏”的设计是满足这个场景的,但是所使用的桥接模式实际上更加符合现在Android手机的应用场景。手机硬件厂商只负责生产手机硬件,而软件厂商只负责发布功能软件,通过将软件组合成一个智能手机)

接下来我们还是通过代码来感受一下桥接模式。

根据我们所画的UML类图先写手机软件。

 1 package day_7_bridge;
 2 
 3 /**
 4  * 手机软件接口
 5  * @author 余林丰
 6  *
 7  * 2016年10月7日
 8  */
 9 public interface Software {
10     void run();
11 }
 1 package day_7_bridge;
 2 
 3 /**
 4  * 通讯录软件,实现手机软件接口
 5  * @author 余林丰
 6  *
 7  * 2016年10月7日
 8  */
 9 public class Contacts implements Software {
10 
11     /* (non-Javadoc)
12      * @see day_7_bridge.Software#run()
13      */
14     @Override
15     public void run() {
16         System.out.println("手机通讯录");
17     }
18 
19 }
 1 package day_7_bridge;
 2 
 3 /**
 4  * 游戏软件,实现手机软件接口
 5  * @author 余林丰
 6  *
 7  * 2016年10月7日
 8  */
 9 public class Game implements Software {
10 
11     /* (non-Javadoc)
12      * @see day_7_bridge.Software#run()
13      */
14     @Override
15     public void run() {
16         System.out.println("游戏软件");
17     }
18 
19 }

我们再来实现手机品牌的实现。

 1 package day_7_bridge;
 2 
 3 /**
 4  * 手机品牌抽象类
 5  * @author 余林丰
 6  *
 7  * 2016年10月7日
 8  */
 9 public abstract class AbstractPhone {
10     protected Software software;
11     
12     public void setSoftware(Software software){
13         this.software = software;
14     }
15     
16     public abstract void run();
17 }
 1 package day_7_bridge;
 2 
 3 /**
 4  * 手机品牌M
 5  * @author 余林丰
 6  *
 7  * 2016年10月7日
 8  */
 9 public class PhoneM extends AbstractPhone {
10 
11     /* (non-Javadoc)
12      * @see day_7_bridge.AbstractPhone#run()
13      */
14     @Override
15     public void run() {
16         this.software.run();
17     }
18 }
 1 package day_7_bridge;
 2 
 3 /**
 4  * @author 余林丰
 5  *
 6  * 2016年10月7日
 7  */
 8 public class PhoneN extends AbstractPhone {
 9 
10     /* (non-Javadoc)
11      * @see day_7_bridge.AbstractPhone#run()
12      */
13     @Override
14     public void run() {
15         this.software.run();
16     }
17 }

客户端测试代码。

 1 package day_7_bridge;
 2 
 3 /**
 4  * @author 余林丰
 5  *
 6  * 2016年10月7日
 7  */
 8 public class Main {
 9 
10     /**
11      * @param args
12      */
13     public static void main(String[] args) {
14         PhoneM phoneM = new PhoneM();
15         phoneM.setSoftware(new Contacts());
16         phoneM.run();
17         phoneM.setSoftware(new Game());
18         phoneM.run();
19     }
20 
21 }

就像上面所提到的,其实这个例子不怎么合适,用现在Android手机一统天下,将软硬件分离才契合这个桥接模式。说了那么多,还是给一个桥接模式的定义:将抽象部分与它的实现部分分离,使它们都可以独立地变化。注意,这里的抽象与实现分离,并不是指的抽象类和派生类的分离,在这个例子中指的就是“手机”这个抽象,应把“手机品牌”和“手机软件”做分离,而不是一味地使用继承关系。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏程序员互动联盟

编程大牛都有哪些基本功

第一部分:什么是基本功 先说说我所理解的基本功是什么:在讨论,计划,工作,策略以及其他一切相关于这个事物的活动时候,可以不用拿出来讨论的“技能”,但是却又是必...

4176
来自专栏程序员互动联盟

C语言能干什么?

C语言几乎是所有语言的实现基础,所以不存在做不了的事情,只是相对来说谁做更合适,编写游戏和软件都不是问题。 为何C语言如此强大? 1、C语言是许多高级计算机语言...

6584
来自专栏python小白到大牛

一行代码结果叹为观止,能做到这么极致的也只有python了

Python 这门语言非常的有趣,不仅可以做高大上的人工智能、大数据、机器学习。还可以用来做 Web、爬虫。还有其它很多的应用。今天我就给大家展示下一行 Pyt...

1533
来自专栏Vamei实验室

Python快速教程 尾声

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明。谢谢!

1332
来自专栏程序员的知识天地

从C++到Python,一个游戏程序员的进阶之路

我的第一份工作是一加国内知名游戏公司的逻辑程序员,必须技能是C++,但是一开始只是写语法和C++很类似的一种脚本(后来知道是从一个开源脚本引擎AngelScri...

1551
来自专栏企鹅号快讯

争论背后的编程语言:谁最容易出bug?

【IT168 评论】10月份,ACM发布了一个关于编程语言对软件质量的影响的研究报告,在报告中有一些关于bug的有趣发现。 研究人员Baishakhi Ray,...

2316
来自专栏博客园

设计模式学习---策略模式

最近在看"Head First 设计模式"这本书,便想将自己所学的记录下来以加深理解,文中肯定有许多不足之处,请各位前辈们指出.

1054
来自专栏C语言C++游戏编程

为何C语言如此强大?到底可以做什么?

C语言几乎是所有语言的实现基础,所以不存在做不了的事情,只是相对来说谁做更合适,编写游戏和软件都不是问题。

1770
来自专栏栗霖积跬步之旅

序章:为什么学习使用kotlin、及kotlin的一些碎碎念

为什么使用kotlin? 当然是因为项目目前的开发语言是kotlin啊! 一方面是想能够尽快适应项目,另一方面,kotlin这门语言独特的语法,确实很吸引我,也...

3316
来自专栏PPV课数据科学社区

对5种主流编程语言的吐槽

接下来要为大家,介绍五款让我又爱又恨的编程语言! 不可否认,想要成为一名优秀的程序员确实是需要掌握多种编程语言。通过这几年的自虐式学习,我也慢慢的掌握了这些编程...

52710

扫码关注云+社区

领取腾讯云代金券