跟着实例学习设计模式(9)-桥接模式bridge(结构型)
桥接模式属于结构型设计模式。
设计意图:将抽象部分与实现部分分离。使它们都能够独立的变化。
一看到设计意图,大家可能有些发懵,我们看到的继承和接口不都是抽象和实现分离的吗?尤其是接口和抽象类都是这种实现啊!那怎么还有这么个桥接的分离呢?
我们先来看个样例。
比如:汽车品牌内置导航仪,我们希望实现,每一个品牌的导航仪都能够在不论什么一个牌子的汽车上安装并启动。
汽车品牌有两个:宝马、奔驰。
导航仪有三个牌子:神行者、北斗、高德。
来看正常的设计,我们肯定是会这种採用继承来实现每一个组合的安装和启动处理的,每一个品牌+导航都须要一个独立的类来实现功能。可是这里有个一个问题。假设我们再添加一个品牌那么就意味着要再添加三个类。每添加一个品牌都是如此。这是一件太痛苦的事啊!所以能找到一种方式不用添加类就能够实现新品牌安装并开启导航仪的功能吗?
来看以下的图,我们将汽车品牌和导航仪品牌做一个组合。
假设能这样组合。那每添加一个汽车品牌时,就仅仅须要添加一个品牌类就好。这个品牌和之前的导航仪组合就能够了。
我们能够看出导航仪和汽车事实上是一种聚合关系,也就是导航仪仅仅是汽车的一部分,而这一部分不随着汽车消亡而消失。所以他们之间是松耦合关系。聚合关系。
桥接模式是遵循了合成/聚合复用原则(稍后我们在介绍该原则),我们来看通用通用类图。
Abstraction:定义抽象类的接口。该接口中定义怎样使用Implementor接口类型对象的方法。
RefinedAbstraction:实现由Abstraction定义的接口方法,可能会有自己的一些私有方法。
Implementor:定义Abstraction抽象的实现,这样的实现是一种嫁接的关系,就像计算机主板和声卡、显卡的关系一样,它能够是一个接口, Implementor接口提供Abstraction抽象接口须要的操作,而 Abstraction则定义了基于这些基本操作的较高层次的操作。
ConcreteImplementor:实现Implementor接口并定义它的详细实现。
让我们来看实例代码,通过实例代码能够更好的理解桥接模式的奇妙。它真的是实现可插拔式的模式。
package com.bridge; /** * 1:汽车品牌抽象类,这个抽象类主要是导航的安装与启动,其他的配件也能够在该类提供方法, * 可是为了开-闭原则。最好能够在另加其他接口。* 2:桥接就是要实现插拔方式的调用。我们想一下主板和插件。主板提供接口定义该接口的功能, * 由插件来实现该接口的功能。这就是桥接的主要思想,抽象与实现分离。 * 3:该类定义了怎样注入一个接口的方法install,并定义了怎样操作注入接口的详细实现的方法open。 * 4:这里事实上能够使用接口,假设使用接口。那就更灵活。以后我再给大家写一个多个接口的样例 * ,每一个配件一个接口。
这样每一个品牌的汽车能够实现多个接口也就能够添加不同的配件了。
* @author gaoxu * 实践出真知。 */ public abstract class AbstractVehicleBrand { /**安装导航方法 * @author gaoxu * @param n */ public abstract void install(INavigator n); /**开启导航 * 开启导航是调用导航接口实现类的方法。事实上那个方法就是我们这种方法的延伸。
* @author gaoxu */ public abstract void open(); }</span>
<span style="font-size:14px;">package com.bridge; /** * @author gaoxu * 实践出真知!*/ public class BMWVehicle extends AbstractVehicleBrand{ //导航 INavigator navigator = null; @Override public void install(INavigator n) { navigator = n; } @Override public void open() { navigator.work(); } }
package com.bridge; /** * @author gaoxu * 实践出真知! */ public class BenzVehicle extends AbstractVehicleBrand{ //导航 INavigator navigator = null; @Override public void install(INavigator n) { navigator = n; } @Override public void open() { navigator.work(); } }导航插件的公共接口,定义了导航的行为方法。
package com.bridge; /** * @author gaoxu * 实践出真知! */ public interface INavigator { public void work(); }
package com.bridge; public class SXZNavigator implements INavigator{ @Override public void work() { System.out.println("我是神行者导航。"); } }
package com.bridge; public class BDNavigator implements INavigator{ @Override public void work() { System.out.println("我是北斗导航!"); } }
我们来看client代码
package com.bridge; public class Client { public static void main(String[] para){ //我们如今是实现不同品牌的汽车,能够安装不同牌子的导航,也就是把汽车和导航聚合了起来。//我们是通过桥接的方式完毕了这样的聚合。桥接方式比继承的方式要更灵活,它是汽车与配件可 以独立各自的发展。
//我们能够实现的聚合关系:宝马+北斗,宝马+神行者,奔驰+北斗。奔驰+身形者 //当然我们还能够给汽车配置很多其它不同的后装配件比如:空气净化器等。
INavigator bdNavigator = new BDNavigator(); INavigator sxzNavigator = new SXZNavigator(); //宝马安装北斗导航 AbstractVehicleBrand bmw = new BMWVehicle(); bmw.install(bdNavigator); bmw.open(); //奔驰安装了神行者导航 AbstractVehicleBrand benz = new BMWVehicle(); benz.install(sxzNavigator); benz.open(); } }
长处:把两种都具有变化的分类实现独立变化,真的是松耦合的典范。
使用范围:多个具有变化的分类共同实现功能时易採用桥接模式。
相关文章
- 机器学习-文本聚类实例-kmeans
- cocos2d-x 3.0游戏实例学习笔记 《跑酷》 第六步--金币&岩石加入而且管理
- Python flask使用实例
- 【JAVA】对异常的理解及实例(不断学习,不断更新)。
- java操作mongoDB数据库的简单实例
- SIP学习(实例详解)
- Qt中标准对话框实例,QObject::tr()的作用
- c#绘制星图靶标实例
- C#使用Mutex实例详解
- PHP 开发 APP 接口 学习笔记与总结 - APP 接口实例 [7] APP 错误日志接口
- 《众妙之门——JavaScript与jQuery技术精粹》——2.6 JavaScript代码复查实例
- Selenium2学习-026-WebUI自动化实战实例-024-获取页面元素
- Selenium2学习-028-WebUI自动化实战实例-026-获取页面元素值或者元素属性值
- Selenium2学习-027-WebUI自动化实战实例-025-JavaScript 在 Selenium 自动化中的应用实例之三(页面滚屏,模拟鼠标拖动滚动条)
- Java学习-019-Properties 文件读取实例源代码
- Java学习-015-CSV 文件写入实例源代码
- Selenium2学习-010-WebUI自动化实战实例-008-Selenium 操作下拉列表实例-Select
- Java学习-012-文件删除实例及源代码
- Vue3+elementplus搭建通用管理系统实例十:动态表单及详情页实现上
- Python实例---游戏人生[类的学习]
- spring mvc学习(一)入门实例
- mysql if使用实例
- 【机器学习】神经网络BP理论与python实例系列