设计模式(十一)桥梁模式(结构型)
概述
在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度?
例子:设想如果要绘制矩形、圆形、椭圆、正方形,我们至少需要4个形状类,但是如果绘制的图形需要具有不同的颜色,如红色、绿色、蓝色等,此时至少有如下两种设计方案:
方案1:
方案2:
对于有两个变化维度(即两个变化的原因)的系统,采用方案二来进行设计系统中类的个数更少,且系统扩展更为方便。设计方案二即是桥接模式的应用。桥接模式将继承关系转换为关联关系,从而降低了类与类之间的耦合,减少了代码编写量。
概念
将抽象部分与实现部分分离,使它们都可以独立的变化。
当一个抽象可能有多个实现时,通常用继承来协调他们。抽象类的定义对该抽象的接口。而具体的子类则用不同的方式加以实现,但是此方法有时不够灵活。继承机制将抽象部分与他的视线部分固定在一起,使得难以对抽象部分和实现部分独立地进行修改、扩充和充用。
适用
- 你不希望在抽象和他的实现部分之间有一个固定的邦定关系,如在程序的运行时刻实现部分应该可以被选择或者切换。
- 类的抽象以及他的视像都可以通过生成子类的方法加以扩充。这时bridge模式使你可以对不同的抽象接口和实现部分进行组合,并对他们进行扩充。
- 对一个抽象的实现部分的修改应该对客户不产生影响,即客户的代码不需要重新编译。
- 你想对客户完全隐藏抽象的实现部分。
- 你想在多个实现间共享实现,但同时要求客户并不知道这一点。
类图
组成角色
抽象类(Abstraction):定义抽象类的接口,维护一个指向Implementor类型对象的指针
扩充抽象类(RefinedAbstraction):扩充由Abstraction定义的接口
实现类接口(Implementor):定义实现类的接口,该接口不一定要与 Abstraction的接口完全一致;事实上这两个接口可以完全不同。一般来讲, Implementor接口仅提供基本操作,而 Abstraction则定义了基于这些基本操作的较高层次的操作。
具体实现类(ConcreteImplementor):实现Implementor接口并定义它的具体实现。
代码
AbstractShape.java
package com.yydcdut;public abstract class AbstractShape {Color color;public AbstractShape(Color color) {super();this.color = color;}public abstract void draw(); }
颜色接口
package com.yydcdut;public interface Color {String getColor(); }
正方形Squre继承图形抽象类
package com.yydcdut;public class Square extends AbstractShape {public Square(Color color) {super(color);}@Overridepublic void draw() {System.out.println("使用"+color.getColor()+"画正方形");}}
圆形Cirlce继承图形抽象类
package com.yydcdut;public class Circle extends AbstractShape {public Circle(Color color) {super(color);}@Overridepublic void draw() {System.out.println("使用"+color.getColor()+"画圆");}}
Red红色实现颜色Color接口
package com.yydcdut;public class Red implements Color {@Overridepublic String getColor() {return "红色";}}
Green绿色实现颜色Color接口
package com.yydcdut;public class Green implements Color {@Overridepublic String getColor() {return "绿色";}}
测试:
package com.yydcdut;public class Main {public static void main(String[] args) {Color color = new Green();AbstractShape shape = new Square(color);shape.draw();}}
效果:
使用绿色画正方形
总结
Bridge模式有以下一些优点:
- 分离接口及其实现部分 一个实现未必不变地绑定在一个接口上。抽象类的实现可以在运行时刻进行配置,一个对象甚至可以在运行时刻改变它的实现。将Abstraction与Implementor分离有助于降低对实现部分编译时刻的依赖性,当改变一个实现类时,并不需要重新编译 Abstraction类和它的客户程序。为了保证一个类库的不同版本之间的二进制兼容性,一定要有这个性质。另外,接口与实现分离有助于分层,从而产生更好的结构化系统,系统的高层部分仅需知道Abstraction和Implementor即可。
- 提高可扩充性 你可以独立地对Abstraction和Implementor层次结构进行扩充。
- 实现细节对客户透明 你可以对客户隐藏实现细节,例如共享 Implementor对象以及相应的引用计数机制(如果有的话) 。
桥接模式的缺点
- 桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
- 桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性。
模拟情景:
现需要提供大中小3种型号的画笔,能够绘制5种不同颜色,如果使用蜡笔,我们需要准备3*5=15支蜡笔,也就是说必须准备15个具体的蜡笔类。而如果使用毛笔的话,只需要3种型号的毛笔,外加5个颜料盒,用3+5=8个类就可以实现15支蜡笔的功能。
实际上,蜡笔和毛笔的关键一个区别就在于笔和颜色是否能够分离。即将抽象化(Abstraction)与实现化(Implementation)脱耦, 使得二者可以独立地变化"。关键就在于能否脱耦。蜡笔的颜色和蜡笔本身是分不开的,所以就造成必须使用15支色彩、大小各异的蜡笔来绘制图画。而毛笔与颜 料能够很好的脱耦,各自独立变化,便简化了操作。在这里,抽象层面的概念是:"毛笔用颜料作画",而在实现时,毛笔有大中小三号,颜料有红绿蓝黑白等5 种,于是便可出现3×5种组合。每个参与者(毛笔与颜料)都可以在自己的自由度上随意转换。
蜡笔由于无法将笔与颜色分离,造成笔与颜色两个自由度无法单独变化,使得只有创建15种对象才能完成任务。
Bridge模式将继承关系转换为组合关系,从而降低了系统间的耦合,减少了代码编写量。
我是天王盖地虎的分割线
源代码:http://pan.baidu.com/s/1dD1Qx01
java桥接.zip
参考:http://blog.csdn.net/hguisu/article/details/7529194
设计模式(十一)桥梁模式(结构型)相关推荐
- GOF设计模式之外观模式(结构型代理模式)
- GOF设计模式之代理模式(结构型代理模式)
- 设计模式(2)结构型模式
结构型模式 结构型模式介绍如何将对象和类组装成较大的结构, 并同时保持结构的灵活和高效. 结构型模式: 适配器模式:用来把一个接口转化成另一个接口.使得原本由于接口不兼容而不能一起工作的那些类可以在一 ...
- 设计模式(三)结构型模式介绍及实例
文章目录 一.适配器模式 1.1 适配器模式定义 1.2 适配器模式主要角色 1.3 适配器模式特点 1.4 适配器模式实现方式 1.4.1 类适配器模式 1.4.2 对象适配器模式 1.5 适配器模 ...
- 设计模式笔记--桥梁模式
常用设计模式有23中,分为: 创建型模式(主要用于创建对象) 1.单例模式 2.工厂方法模式 3.抽象工厂模式 4.建造者模式 5.原型模式 行为型模式 (主要用于描述对象 ...
- 享元模式 - 结构型模式
模式类型: Flyweight 享元模式 - 结构型模式 意图: The intent of this pattern is to use sharing to support a ...
- 设计模式(四)结构型模式
前言 结构型设计模式,主要研究: 主要有哪些场景使用结构型设计模式: 每种场景应该使用何种设计模式: 以程序中的功能为核心,研究程序功能的组织结构.所以这一章,我们要把"功能结构" ...
- 【设计模式】设计模式总结 ( 七大设计原则 | 创建型模式 | 结构型模式 | 行为型模式 ) ★★★
文章目录 一.七大设计原则 1.开闭原则 2.依赖倒置原则 3.单一职责原则 4.接口隔离原则 5.迪米特原则 6.里氏替换原则 7.合成复用原则 二.创建型模式 0.简单工厂模式 ( 不属于 GOF ...
- 设计模式-桥接模式-结构型
定义: 将抽象部分与实现部分分离,使他们都可以独立的进行变化 类型: 结构型 理解: 如果一个类只有一个纬度的变化,那么可以使用继承,但是如果有多个维度变化时,使用继承会导致类的大量增加. 例如:现在 ...
最新文章
- Asp.Net MVC2.0 Url 路由入门---实例篇
- Biopython-Chapter3.生物序列对象
- kafaka使用 消息队列_Java使用消息队列还是直接使用线程池ExecutorService异步处理?...
- 介绍理想工作计算机 英语作文,我的理想工作英语作文(精选5篇)
- 【整理】SAP PM工厂维护模块初识
- GDCM:获取dicom文件Sequence的长度的测试程序
- 19级:班级日常分享 | 一天一瞬间
- Scala 知识点掌握1
- Kafka核心源码解析 - KafkaController源码解析
- Comet4J推技术在SSHE三大框架中应用-linux下亲测可用
- Java 即将迎来转折点
- oracle 存储过程深入学习与应用
- 基于springboot的民办职业学校缴费系统
- JDK动态代理和CGLIB动态代理介绍
- 各浏览器驱动下载地址及selenium配置
- 摩拜、ofo抢着用的NB-IoT技术,听说你还不知道!?
- 基于JAVA的GUI编程的的迷宫游戏 2020-12-15
- 物联卡的测试期、沉默期、计费期你都知道吗
- 我们是怎么看中国企业服务的​
- unity中AO、metallic、roughness贴图的使用方式
热门文章
- 【转】Matlab中特殊符号的写法
- c语言随机三位数,【分享代码】弥补c语言随机数不足
- java 输出 三角形_Java实现输出三角形
- 【数字信号处理】傅里叶变换性质 ( 共轭对称与共轭反对称图像示例 | 实序列中共轭对称是偶对称 | 实序列中共轭反对称是奇对称 )
- 【错误记录】PyCharm 运行 Python 程序报错 ( PEP 8: E402 module level import not at top of file )
- 【IOC 控制反转】Android 布局依赖注入 ( 布局依赖注入步骤 | 布局依赖注入代码示例 )
- 【Flutter】插件包选择 ( 查看文档是否全面 | 查看插件包的更新版本次数 | 查看使用示例 | 查看 GitHub 项目的 Star Fork Issues )
- 【MATLAB】变量 ( 特殊变量和常量 | 关键字 | 调用优先级 | 数值显示格式 )
- 【C++ 语言】面向对象 ( 函数重载 | 运算符重载 | 运算符重载两种定义方式 | 拷贝构造方法 | RVO 优化 | NRVO 优化 )
- 【Android 应用开发】Activity 状态保存 OnSaveInstanceState参数解析