- 浏览: 2307996 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (314)
- JAVA基础知识 (54)
- Java-IO/FIle (16)
- Java-JDBC (4)
- JAVA-新增特性-注解 (3)
- Java-枚举 (2)
- Java-泛型 (1)
- Java-多线程 (15)
- Java-XML (4)
- Java-JMS(消息服务) (4)
- Java-JVM (0)
- Web Service服务 (7)
- Jsp (10)
- js (18)
- Struts框架 (11)
- Spring框架 (29)
- Hibernate框架 (28)
- Spring Boot框架 (2)
- ExtJS前端框架 (29)
- Jquery js库 (8)
- JUnit框架 (8)
- Selenium 测试 (1)
- NoSql---Redis (6)
- ORACLE数据库 (45)
- MySQL数据库 (4)
- tomcat (3)
- Nginx反向代理服务器 (4)
- web应用服务器通用知识 (3)
- 开发工具IDE (14)
- UML建模 (1)
- SVN CVS 版本管理 (6)
- git 分布式版本管理 (4)
- 报表设计 (5)
- 文件上传下载 (2)
- 数据算法 (1)
- 存储过程 (5)
- JSON 相关 (1)
- OGNL表达式 (3)
- Util工具包 (9)
- 设计模式 (15)
- linux 相关 (3)
- life think (3)
- 工作流管理框架 (1)
- 大数据-Hadoop (1)
最新评论
-
huih:
很不错的文章
SpringMVC+Hibernate+Spring 简单的一个整合实例 -
calm01:
学习了.
Spring <bean>标签属性 Autowire自动装配(转载) -
lizhenlzlz:
我的也是拦截不了service层
SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)(转载) -
josh_123:
讲的不错,很详细,如果quartz定时任务类采用不继承任何类的 ...
Spring,jdk定时任务的几种实现以及任务线程是串行还是并行执行(转载) -
human_coder:
你知道eclipse调试怎么可以回调吗?有时候总是调快了,不能 ...
Debug---Eclipse断点调试基础
摘要:本文首先解释了Bridge模式的定义。然后通过一个例子,一步步将Bridge模式实现。
在一切开始之前,请允许我先给出三条经典名言:Design to interfaces. Find what varies and encapsulate it. Favor composition over inheritance.后面我们会反复,并且是反反复复的用到。我认为在做设计的时候这三句话要牢牢的印在脑子里。
一. 定义
根据GOF的定义,Bridge模式的目的是“解耦抽象与它的实现,以便二者可以独立的变化。”这个定义中最容易误解的“抽象”与“它的实现”。因为这两个词在面向对象的语言中都有对应的关键字。在Java中即是“abstract”和“implement”,所以很容易造成困惑的是认为要解耦一个抽象类和它的实现类。实际上,这里实现是指的抽象类和它的派生类用以实现自己的对象,进一步说就是这里的抽象指的是一个概念或者说是一个继承体系中的对象,而实现被抽象使用并完成自己的功能。举个例子,这是吕震宇兄想出的一个例子(http://www.cnblogs.com/zhenyulu/articles/67016.html),这是我见过的最经典的例子了,以至于我不得不在这里重复一遍:
小时候我们都用蜡笔画画,一盒蜡笔12种颜色。一开始我都是用最小号的蜡笔画个太阳公公、月亮婆婆足够了。后来开始画一些抽象派的作品,就得换中号的了,要不然画个背景都要描半天,好一盒中号的也是12种颜色。再后来我开始转向豪放派,中号就有些捉襟见肘了,只好换大号的了,好一盒大号的也只有12种颜色。你看,像我这样不太出名的画家就需要36种画笔,哇,太麻烦了。但是据我观察,另一些比我出名的画家倒是没有这么多笔,他们只有几把刷子和一些颜料,这样就解决了蜡笔的“种类爆炸”问题。如下图所示,注意图也是从吕兄的网站偷来的。
我要用36种蜡笔
齐白石老先生只用3种毛笔和12种颜料
回到上面的定义,定义里面的抽象指的就是毛笔,实现就是颜料。颜料被毛笔使用,用以完成毛笔的功能。
(http://www.niufish.com/books/Pattern/com/niufish/pattern/bridge/package-use.html)
在下认为上图中有以下几点可以变通:
1. Abstraction与Implementor的聚合关系。该关系可以由RefinedAbstraction和Implementor的聚合关系代替。理由是Java编程的时候Abstraction可能会实现为interface,不能与Implementor构成聚合关系。
2. Operation方法不一定在Abstraction中做实现,理由同上,但是必须声明。
可见在Bridge模式中有两个继承体系,为了方便描述我们称左边的为Abstraction继承体系,右边为Implementor继承体系。Abstraction使用Implementor完成自己的功能。同时,该模式允许Abstraction和Implementor各自独立变化(所谓变化,我认为就是派生)。
二. 解决的问题
上面已经说了,提出毛笔的概念目的是解决蜡笔的“种类爆炸”问题。3×12变成了3+12,并且在将来毛笔型号和颜料种类可以独立的扩充。上面的例子在说明这种设计模式的特点和优势上很有好处,但是毕竟我们实际编码中很少这么幸运的碰上这么简单的问题。下面我用一个相对复杂的问题来重新描述这个模式,关于蜡笔和毛笔的故事的代码可以到上面给出的链接查找。
三. 一个更加复杂的例子
这里我们给出一个更为复杂的例子,并且用一种循序渐进的方式描述,逐渐加入新的功能和约束条件。设想我们要做一个编辑器(Editor),可以打开文本文件,但是不同的文件要求用不同的编辑器打开。比如“.txt”文件用文本编辑器打开,而“.xml”文件用xml编辑器打开。
代码如下:
Editor接口
package com.gemplus.editor;
public abstract interface Editor {
public void openFile(String path);
}
TextEditor实现
package com.gemplus.editor;
public class TextEditor implements Editor {
public void openFile(String path) {
System.out.println("Open file with Text Editor. FileName: " + path);
}
}
XMLEditor实现
package com.gemplus.editor;
public class XMLEditor implements Editor {
public void openFile(String path) {
System.out.println("Open file with XML Editor. FileName: " + path);
}
}
Client
package com.gemplus.editor;
public class Client {
public static void main(String[] args) {
Editor xmlEditor = new XMLEditor();
xmlEditor.openFile("test.xml");
Editor textEditor = new TextEditor();
textEditor.openFile("test.txt");
}
}
输出
Open file with XMLEditor. FileName: test.xml
Open file with Text Editor. FileName: test.txt
到目前为止,我们什么模式也没用到。不过我们还是用到了一项伟大的技术多态,还有就是对接口编程。代码写的还算优雅,只是没有写注释。
接下来我们要增加一个功能,与其说是功能,不如说是一项约束。就是,我不希望客户端了解那些文件要由xmlEditor打开,哪些由textEditor打开。但是总要有人知道,对吧?这项看似直观的约束往往被忽略,或者在潜意识中没有意识到。为了简单起见,我们引入一个简单工厂EditorImpl。
public class SmartEditor implements Editor {
private static Editor textEditor = new TextEditor();
private static Editor xmlEditor = new XMLEditor();
public void openFile(String path) {
if (path.endsWith(".xml")) {
xmlEditor.openFile(path);
} else {
textEditor.openFile(path);
}
}
}
Client也要做相应修改
public class Client {
public static void main(String[] args) {
// Editor xmlEditor = new XMLEditor();
// xmlEditor.openFile("FileName");
// Editor textEditor = new TextEditor();
// textEditor.openFile("FileName2");
Editor editor = new SmartEditor();
editor.openFile("test.xml");
editor.openFile("test.txt");
}
}
输出结果与修改之前完全一样,但是现在Client端已经不需要知道应该使用哪个Editor了,这其实也是对Find what vary and encapsulate it的应用。另外一点,也可以请大家注意在EditorImpl的实现中,即继承了Editor接口又使用了组合这其实是联合inheritance和composition的优点。Javaworld上有一篇文章(作者Bill Venners)就是讲这个技巧和使用方法的,我找了半天没找到,以后找到再把链接添上。
先别高兴太早,我们看看目前这种设计有什么问题。SmartEditor在充满了技巧和高级的、伟大的技术的同时,你有没有觉得它管的东西太多了呢?一个Editor要去关心文件名的问题,不错SmartEditor出现的目的就是要来关心文件名,然而从概念上讲,仍然不是好的设计。我们来看看什么在变化?答案是文件类型。OK,封装之!
我们把它称作什么呢?对应与Edtior,我们不妨称之为Editable。(说实话,我这样这个概念建立起来有一些生硬,但是你可以想像一下:如果被编辑的东西是更加复杂的呢?我所取的例子实际上是我工作中的一个例子,要编辑的东西要比这里描述的复杂的多!)
简单之极,以至于我觉得没有必要给出代码。但是第一次写文章,总要给大家留点好印象。
public class FileEditable implements Editable {
Editor editor;
String filePath;
public FileEditable(Editor editor, String filePath) {
this.editor = editor;
this.filePath = filePath;
}
public void open() {
editor.openFile(filePath);
}
}
Client端
public class Client {
public static void main(String[] args) {
Editable editableText = new FileEditable(new TextEditor(), "test.txt");
Editable editableXML = new FileEditable(new XMLEditor(), "test.xml");
editableText.open();
editableXML.open();
}
}
输出仍然没有变化。(前面做的其实也可以算作是重构吧,可观察行为没有变化)
不得不承认,现在客户端又需要了解什么样的文件用什么编辑器打开了。但是一个小的变化就可以避免这一点。为FileEditable增加一个不包含Editor参数的构造函数。
public FileEditable(String filePath) {
this.filePath = filePath;
if (filePath.endsWith(".xml")) {
editor = new XMLEditor();
} else {
editor = new TextEditor();
}
}
客户端,这里就不给出了。
现在该是增加功能的时候了。现在我们要求,用户不但可以打开文件也有可能用这个Editor来编辑一段文字,即字符串。我们假设,所有的Editor都可以编辑文件和字符串。我们为Editor增加一个方法:openString。前面我们说了,Bridge模式中有两个继承体系,两边可以独立变化。现在我们有了两个Editable,即两种可编辑体:文件和字符串。也可以看出我们当初把Editable封装起来多么的英明神武啊!!
在Editable的继承体系中又增加了一员:StringEditable。
虽然我前面已经说了,Abstraction和Implementor的聚合关系可以由派生类RefinedAbstraction和Implementor的聚合关系代替,为了与经典模式类图保持尽量的相似,以便大家容易理解,我们还是在StringEditable和FileEditable上面加了一层:EditableImpl。
好了,我们已经实现了Bridge模式。不过这里面还是有一点让人不舒服的地方,就是Editor中包含的两个方法,实际上对应了两种Editable。也许是这个例子举的不好。但是《设计模式 explained》中的例子和本例大同小异。
我也是刚刚开始学习设计模式,如果有什么不对的地方请大家指出。接下来,我会继续这个例子,增加一个更加复杂的功能:可以嵌套组合的Editor。比如对于同一个文件我们可能希望有两种打开方式,以网页为例,我们希望在一个Editor中包含两个子Editor,分别显式源代码和页面效果。这里面会用到Composite模式。
参考资料:
1. http://www.cnblogs.com/zhenyulu/articles/67016.html
《设计模式随笔-蜡笔与毛笔的故事》本文对于Bridge模式给了一个相当漂亮的比喻,并且给出了代码示例。
2. http://www.cnblogs.com/zhenyulu/articles/62720.html
《设计模式(16)-Bridge Pattern》这篇文章没有仔细看,前面的角色定义和解释很精辟。
3. http://www.cnblogs.com/idior/articles/97283.html
《Bridge Strategy 和State的区别》个人认为,作者在Bridge和Strategy模式的区别上面有误解。下面有我的回复:
我倒是不赞同楼主所说在“蜡笔与毛笔的故事”中“缺少被抽象的行为”的说法。Bridge模式中解耦的是“抽象”与“实现”。这里的实现不一定是对“行为”的抽象,按照《Design Pattern Explained》一书中所说,这里实现是指的抽象类和它的派生类用以实现自己的某个对象(本身是抽象与其派生类构成的继承体系,要不怎么变化呢)。进一步说就是这里的抽象指的是一个概念或者说是一个继承体系中的对象,而实现则是被抽象使用并完成自己的功能的另一个继承体系。桥梁模式的目的就是让这两个继承体系可以,独立的变化、派生。蜡笔与毛笔的故事中毛笔(第一个继承体系)和颜料(第二个继承体系)可以独立的变化,所以我认为这是个非常恰当的桥梁模式的例子。
继续:)
我觉得区分两个模式的方法不是从模式的实现上面看,因为一个模式的实现往往夹杂了其它的模式,比如idior给的第一个例子中就有Template Method模式。我赞成吕震宇的说法,这里面有Bridge模式的影子,甚至我觉得不止是影子,这本身是一个Bridge模式的例子。
区分两个模式的方法应该从解决的问题上看,也就是从context上分析。
我觉得简单的说Strategy模式是从N变化为1+N,原来有N个类但是这N个类里面只有某个算法的区别,我们把N个算法提取出来就变成了1个抽象类(不要理解成Java中的abstract class,而是这个抽象类表示一个概念)和N个实现类(同理,不要理解成对前面那个抽象类的实现,而是辅助实现抽象类的某个功能的一个继承体系)。注意这里只有一个继承体系。
而Bridge模式是从M×N变化为M+N,原来系统中有M×N个类,但是从中可以提取出N个算法(或者辅助类)和M个主体(我想不出一个好的名次)。这样构成了两个继承体系,N个算法(颜料)构成一个继承体系,M个主体类(毛笔的不同型号)构成一个继承体系。两个继承体系可以独立的变化。
从解决的问题上看,二者都要解决重复代码的问题,但是前者不强调锥把(见吕震宇的回复)的变化,而后者强调,并且强调锥头和所有锥把的兼容。我认为这才是二者的根本区别。
这是我个人的理解,与楼主商榷。
4. http://www.niufish.com/books/Pattern/com/niufish/pattern/bridge/package-use.html
设计模式速查,很不错
发表评论
-
设计模式遵循的六大基本原则(转)
2016-05-12 17:10 903转载地址:http://www.uml.org.cn/sjm ... -
Proxy-代理模式(转载 动态生成代理对象那块挺有意思)
2014-11-25 17:31 4823Java动态代理模式 1. 代理:一个角色代表别一个角色来 ... -
Web架构师成长之路(转载)
2014-09-01 11:16 1069本人也是coding很多年,虽然很失败,但也总算有点失败的心 ... -
享元模式-Flyweight(转载)
2014-07-10 18:13 1225Flyweight在拳击比赛中指最轻量级,即“蝇量级” ... -
重构方法及简述列表(转载)
2014-07-10 15:05 1604最近,我以最快的速度浏览了一下《重构-改善既有代码设计》, ... -
原型模式--Prototype
2014-07-03 15:21 1130定义:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新 ... -
外观模式(门面模式)--Facade
2014-06-30 16:53 1447外观模式是一种使用 ... -
装饰者模式-Decorator
2014-06-24 11:38 1069装饰者模式:动态地将责任附加到对象上,若要扩展对象,装饰者模 ... -
组合模式-Component(转)
2014-06-18 10:50 2594一、组合模式简介(Brief Introduction) ... -
Bridge-桥接模式(转载)
2014-06-16 16:42 1335在开始学java的时候老师讲到继承的时候,总是喜欢用一个例子 ... -
适配器模式 (转载)
2014-06-13 11:06 13241. 概述 将一个类的接口转换成客户希望的另外一个接 ... -
23种设计模式包括哪些
2014-06-12 16:38 894一共23种设计模式! 按照目的来分,设计模式可以分为 ... -
java建造者模式(Builder)(转载)
2014-06-12 16:35 1117建造者模式针对复杂对象由于需求变化,造成组成它的各部分经常变 ... -
OO几条设计原则
2013-01-16 11:31 118700设计原则: 封装变化; 多用组合,少用继承; 针 ...
相关推荐
Bridge模式是一种设计模式,属于结构型模式之一,其主要目的是将抽象部分与实现部分分离,使得两者可以独立地进行变化。这种模式的核心思想是“抽象不应该依赖于具体,而应该依赖于抽象”。Bridge模式通过引入一个...
本文将介绍 Bridge 模式,它是一种结构型设计模式,用于解耦抽象与实现,增强软件系统的灵活性和可扩展性。 二、Bridge 设计模式的别名 Handle/Body 三、Bridge 设计模式的意图 Bridge 设计模式是 Java 中的一种结构...
本资料主要探讨了Docker的网络桥接模式(Bridge模式)以及其默认网络设备docker0,这对于理解和运用Docker服务至关重要。 首先,Docker的Bridge模式是Docker容器默认的网络模式。在这个模式下,每个容器都会被分配...
Bridge模式是一种设计模式,主要目的是将抽象部分与实现部分解耦,使得它们可以独立地进行变化。在Java编程中,这种模式的应用可以帮助我们构建更灵活、可扩展的系统。Bridge模式通常由四个主要角色组成:抽象...
Bridge模式是对抽象和具体的进一步抽象。假设你有一个抽象类,一个具体类,现在需要将两者的变化都考虑进去,这就需要bridge。这是经典设计模式中唯一的可以同时处理抽象和具体同时变化的设计模式
Docker在创建容器时有四种网络模式,bridge为默认不需要用--net去指定,其他...那Docker为网络bridge模式指定容器ip该如何实现呢?下面通过通过这篇文章一起看看吧,文中给出了详细的示例代码,有需要的可以参考借鉴。
桥模式(Bridge模式)是一种设计模式,主要用于将抽象部分与实现部分解耦,使得它们能够独立地变化。在Java中,这种模式可以帮助我们构建更加灵活和可扩展的系统。以下是关于桥模式的详细解释: 首先,理解桥模式的...
软件设计模式,共包含二十多种模式,做IT的必备知识呀!
在给定的文件列表中,我们可以看到涉及到Bridge模式的一些关键组件: 1. **Abstraction**(抽象类):这是桥接模式的核心抽象部分,定义了客户需要的接口,并持有一个指向实现部分的指针。在`abstraction.cpp`和`...
这就要使用Bridge模式。 意图 将抽象部分与实现部分分离,使它们都可以独立的变化。[GOF《设计模式》] 结构图图1Bridge模式结构图 生活中的例子 桥接模式将抽象部分与它的实现分离,使它们能够独立地变化。一个...
《Java实现的23种设计模式——Bridge模式详解》 设计模式是软件工程中的宝贵经验总结,它们为解决常见问题提供了可复用的解决方案。在众多设计模式中,Bridge模式是一种结构型模式,旨在将抽象部分与其实现部分分离...
Java设计模式中的Bridge模式是一种结构型设计模式,其主要目的是将抽象部分与其实现部分分离,使得两者可以独立地进行变化。在Bridge模式中,抽象类(或接口)不直接包含实现,而是通过一个引用(或接口)指向实现类...
在上述例子中,Bridge模式被用来解决咖啡种类的问题。咖啡可以按照杯型(中杯、大杯)和是否加奶(加奶、不加奶)来分类。如果简单地使用继承,会形成一个四层的类结构,这将导致类的复杂性和扩展困难。Bridge模式...
我们需要选择Bridge模式,并启用DHCP使能。这将允许电脑连接光猫时可以自动获得IP地址。然后,我们需要访问光猫的配置页面,并勾选业务模式为INTERNET,vlan模式改为TAG,vlanid为200,802.1p优先级为6。 步骤3:...
Bridge 模式是一种结构型模式,用于提供一种分离对象的接口和实现的接口。Bridge 模式的优点是可以提供一种统一的分离对象的接口和实现的接口,减少了代码的耦合度。Bridge 模式的缺点是它可能会增加代码的复杂度。 ...
Bridge 模式是一种结构型设计模式,主要用于将抽象部分与实现部分分离,使得它们可以独立地变化。它可以使得抽象部分和实现部分之间的绑定变得松散,从而提高了系统的灵活性和可维护性。 2. ACE 框架中的 Bridge ...