桥(Bridge)模式
Bridge定义:将抽象和行为划分开来,各自独立,但能动态的结合。
为什么使用桥模式
通常,当一个抽象类或接口有多个具体实现(concrete subclass),这些concrete之间关系可能有以下两种:
- 这多个具体实现之间恰好是并列的,如前面举例,打桩,有两个concrete class:方形桩和圆形桩;这两个形状上的桩是并列的,没有概念上的重复,那么我们只要使用继承就可以了。实际应用上,常常有可能在这多个concrete class之间有概念上重叠。那么需要我们把抽象共同部分和行为共同部分各自独立开来,原来是准备放在一个接口里,现在需要设计两个接口,分别放置抽象和行为。
例如,一杯咖啡为例,有中杯和大杯之分,同时还有加奶 不加奶之分。如果用单纯的继承,这四个具体实现(中杯 大杯 加奶 不加奶)之间有概念重叠,因为有中杯加奶,也有中杯不加奶,如果再在中杯这一层再实现两个继承,很显然混乱,扩展性极差。那我们使用Bridge模式来实现它。如何实现桥模式
以上面提到的咖啡 为例。我们原来打算只设计一个接口(抽象类),使用Bridge模式后,我们需要将抽象和行为分开,加奶和不加奶属于行为,我们将它们抽象成一个专门的行为接口。
先看看抽象部分的接口代码:
public abstract class Coffee{
CoffeeImp coffeeImp;
public void setCoffeeImp() {
this.CoffeeImp = CoffeeImpSingleton.getTheCoffeImp();
}
public CoffeeImp getCoffeeImp() {return this.CoffeeImp;}
public abstract void pourCoffee();
}
其中CoffeeImp 是加不加奶的行为接口,看其代码如下:
public abstract class CoffeeImp{
public abstract void pourCoffeeImp();
}现在我们有了两个抽象类,下面我们分别对其进行继承,实现concrete class: //中杯
public class MediumCoffee extends Coffee{
public MediumCoffee() {setCoffeeImp();}
public void pourCoffee(){
CoffeeImp coffeeImp = this.getCoffeeImp();
//我们以重复次数来说明是冲中杯还是大杯 ,重复2次是中杯
for (int i = 0; i < 2; i++){
coffeeImp.pourCoffeeImp();
}
}
}//大杯
public class SuperSizeCoffee extends Coffee{
public SuperSizeCoffee() {setCoffeeImp();}
public void pourCoffee(){
CoffeeImp coffeeImp = this.getCoffeeImp();
//我们以重复次数来说明是冲中杯还是大杯 ,重复5次是大杯
for (int i = 0; i < 5; i++){
coffeeImp.pourCoffeeImp();
}
}
} 上面分别是中杯和大杯的具体实现.下面再对行为CoffeeImp进行继承: //加奶
public class MilkCoffeeImp extends CoffeeImp{
MilkCoffeeImp() {}
public void pourCoffeeImp(){
System.out.println("加了美味的牛奶");
}
}//不加奶
public class FragrantCoffeeImp extends CoffeeImp{
FragrantCoffeeImp() {}
public void pourCoffeeImp(){
System.out.println("什么也没加,清香");
}
} Bridge模式的基本框架我们已经搭好了,别忘记定义中还有一句:动态结合,我们现在可以喝到至少四种咖啡:- 中杯加奶中杯不加奶大杯加奶大杯不加奶
看看是如何动态结合的,在使用之前,我们做个准备工作,设计一个单态类(Singleton)用来hold当前的CoffeeImp: public class CoffeeImpSingleton{
private static CoffeeImp coffeeImp;
public CoffeeImpSingleton(CoffeeImp coffeeImpIn)
{this.coffeeImp = coffeeImpIn;}
public static CoffeeImp getTheCoffeeImp(){
return coffeeImp;
}
} 看看中杯加奶 和大杯加奶 是怎么出来的: //拿出牛奶
CoffeeImpSingleton coffeeImpSingleton = new CoffeeImpSingleton(new MilkCoffeeImp());//中杯加奶
MediumCoffee mediumCoffee = new MediumCoffee();
mediumCoffee.pourCoffee();//大杯加奶
SuperSizeCoffee superSizeCoffee = new SuperSizeCoffee();
superSizeCoffee.pourCoffee(); 注意:Bridge模式的执行类如CoffeeImp和Coffee是一对一的关系,正确创建CoffeeImp是该模式的关键。 实例2.我们假设有一座桥,桥左边为A,桥右边为B,A有A1,A2,A3等,表示桥左边的三个不同地方,B有B1,B2,B3等,表示桥右边的三个不同地方,假设我们要从桥左侧A出发到桥的右侧B,我们可以有多重方案,A1到B1,A1到B2,A1到B3,A2到B1...等等,以此为例
桥接口:Qiao
1 public interface Qiao {
2 //目的地B
3 void targetAreaB();
4 }目的地B1,B2,B3:
1 /**
2 * 目的地B1
3 */
4 public class AreaB1 implements Qiao {
5
6 @Override
7 public void targetAreaB() {
8 System.out.println("我要去B1");
9 }
10
11 }
12
13 /**
14 * 目的地B2
15 */
16 public class AreaB2 implements Qiao {
17
18 @Override
19 public void targetAreaB() {
20 System.out.println("我要去B2");
21 }
22
23 }
24
25 /**
26 * 目的地B3
27 */
28 public class AreaB3 implements Qiao {
29
30 @Override
31 public void targetAreaB() {
32 System.out.println("我要去B3");
33 }
34
35 }抽象来源地A:AreaA
1 public abstract class AreaA {
2 //引用桥接口
3 Qiao qiao;
4 //来源地
5 abstract void fromAreaA();
6 }来源地A1,A2,A3:
1 /**
2 * 来源地A1
3 */
4 public class AreaA1 extends AreaA {
5
6 @Override
7 void fromAreaA() {
8 System.out.println("我来自A1");
9 }
10
11 }
12
13 /**
14 * 来源地A2
15 */
16 public class AreaA2 extends AreaA {
17
18 @Override
19 void fromAreaA() {
20 System.out.println("我来自A2");
21 }
22
23 }
24
25 /**
26 * 来源地A3
27 */
28 public class AreaA3 extends AreaA {
29
30 @Override
31 void fromAreaA() {
32 System.out.println("我来自A3");
33 }
34
35 }测试类:Clienter
1 public class Clienter {
2 public static void main(String[] args) {
3 AreaA a = new AreaA2();
4 a.qiao = new AreaB3();
5 a.fromAreaA();
6 a.qiao.targetAreaB();
7 }
8 }运行结果:
我来自A2
我要去B3如何,只要你认真看完了实例,你就明白了这种模式的好处,现在我们要添加来源地和目的地,只要继续继承AreaA和实现Qiao即可,之前我所说的绑定,正式此处将桥与目的地绑定在一起,使用一个接口完成。
其实要完成桥接模式,注意点并不多,重在理解模式的使用场景。
注意点:
1、定义一个桥接口,使其与一方绑定,这一方的扩展全部使用实现桥接口的方式。
2、定义一个抽象类,来表示另一方,在这个抽象类内部要引入桥接口,而这一方的扩展全部使用继承该抽象类的方式。
其实我们可以发现桥接模式应对的场景有方向性的,桥绑定的一方都是被调用者,属于被动方,抽象方属于主动方。
其实我的JDK提供的JDBC数据库访问接口API正是经典的桥接模式的实现者,接口内部可以通过实现接口来扩展针对不同数据库的具体实现来进行扩展,而对外的仅仅只是一个统一的接口调用,调用方过于抽象,可以将其看做每一个JDBC调用程序(这是真实实物,当然不存在抽象)
下面来理解一下概念:
桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。
这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类。这两种类型的类可被结构化改变而互不影响。
理解:此处抽象化与实现化分别指代实例中的双方,而且实现化对应目的地方(通过实现桥接口进行扩展),抽象方对应来源地方(通过继承抽象类来进行扩展),如果我们不使用桥接模式,我们会怎么想实现这个实例呢?很简单,我们分别定义来源地A1、A2、A3类和目的地B1、B2、B3,然后具体的实现就是,A1到B1一个类,A1到B2一个类,等,如果我们要扩展了A和B ,要直接增加An类和Bn类,如此编写不说类内部重复性代码多,而且还会导致类结构的急剧膨胀,最重要的是,在通过继承实现路径的时候,会造成双方耦合性增大,而这又进一步加剧了扩展的复杂性。使用桥结构模式可以很好地规避这些问题:重在解耦。
- 中杯加奶中杯不加奶大杯加奶大杯不加奶
桥(Bridge)模式的更多相关文章
- 设计模式(六)桥连模式Bridge(结构型)
设计模式(六)桥连模式Bridge(结构型) 1. 概述 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够 ...
- Java设计模式(6)桥模式(Bridge模式)
Bridge定义:将抽象和行为划分开来,各自独立,但能动态的结合. 为什么使用桥模式 通常,当一个抽象类或接口有多个具体实现(concrete subclass),这些concrete之间关系可能有以 ...
- Bridge 模式
Bridge 模式将抽象和行为划分开来,各自独立,但能动态的结合.在面向对象设计的基本概念中,对象这个概念实际是由属性和行为两个部分组成的,属性我们可以认为是一种静止的,是一种抽象,一般情况下,行为是 ...
- 设计模式之——bridge模式
Bridge模式,又叫桥接模式,是针对同一接口进行扩展与实现操作的一种设计模式. 这种模式,与之前学过的适配器模式具有相似的地方,也有不同的地方,下面就让我们一一解析吧. 首先,我们要了解到,为什么需 ...
- (原创)composite模式和bridge模式是天生的好朋友
composite模式的意图是:将对象组合成树形结构以表示“部分-整体”的层次结构.composite使得用户对单个对象和组合对象的使用具有一致性.它的类图如下: composite模式的实现分为透明 ...
- Structual设计--Bridge模式
1.意图 将抽象部分与它的实现部分分离.使他们都能够独立地变化. 2.别名 Handle/Body 3.动机 当一个抽象对象可能有多个实现时,通经常使用继承来协调它们.抽象类定义对该抽象的接口.而详细 ...
- Java 实现桥接(Bridge)模式
类图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamp3d21scDQ1Ng==/font/5a6L5L2T/fontsize/400/fill/I0 ...
- 设计模式(九)Bridge模式
Bridge模式就是将类的功能层次结构和类的实现层次结构连接起来. 类的功能层次结构就是根据实际非抽象类来说的,也就是父类具有基本功能,然后在子类中增加新功能.用于增加新功能. 类的实现层次结构就是根 ...
- 设计模式C++描述----09.桥接(Bridge)模式
一. 举例 N年前: 计算机最先出来时,软件和硬件是一绑在一起的,比如IBM出了一台电脑,上面有一个定制的系统,假如叫 IBM_Win,这个IBM_Win系统当然不能在HP电脑上运行,同样HP出的HP ...
随机推荐
- [SDOI2015]约数个数和 --- 简单反演
求\(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}d(ij)\) 不知道怎么讲..... 首先考虑\(d(ij)\)究竟是什么 首先,很自然地想到,既然是求\( ...
- [POJ2749]Building roads(2-SAT)
Building roads Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 8153 Accepted: 2772 De ...
- [Codeforces #172] Tutorial
Link: Codeforces #172 传送门 A: 一眼看上去分两类就可以了 1.每个矩形只有两条边相交,重合的形状为菱形 2.每个矩形四条边都有相交 对于情况1答案为$h*h/sin(a)$ ...
- 利用BusyBox ~私人定制 My LINUX~
前言 我在今天在这里跟大家详细地探讨一下Linux系统的定制过程和实现例如.用户能够远程登录:和Nginx能够稳定地运行在我们私人定制的LINUX系统上.一步一步从头开始定制属于我们自己的系统. 正文 ...
- html端编码规范
理想的方式是让HTML只用于定义内容呈现的结构,让CSS控制内容呈现的样式,而所有功能的实现定义在JavaScript中
- Eclipse中在android项目中出现新建一个Activity后,出现整个project的报错以及包导入以后无法执行等等情况分析。
今天用Eclipse去写android项目,然后后面须要建一个Blank Activity后,非常正常的建立的.然后那个Activity是基于ActionBarAtivity,要导入v7,结果由于这 ...
- informatica powercenter学习笔记(一)
本文转摘:http://blog.itpub.net/22377317/viewspace-677137/ 1 informatica powercenter的下载: 方法一:去年我是在ORACLE ...
- dedecms织梦 v5.6 两处跨站漏洞
漏洞版本: dedecms织梦 v5.6 漏洞描述: DedeCMS内容管理系统软件采用XML名字空间风格核心模板:模板全部使用文件形式保存,对用户设计模板.网站升级转移均提供很大的便利,健壮的模板标 ...
- Fragment 创建 传递参数 跳转【典例】
Fragment一定要有一个无参的构造方法! 因为当Activity因屏幕旋转或者因内存不足被系统杀死时,会导致Activity被重新创建,而当Activity被重建时,FragmentManager ...
- 【Python】Python中的深浅拷贝
[转]python 复制(拷贝)对象 -- ::| 分类: Python |举报|字号 订阅 下载LOFTER我的照片书 | 需求: 你想复制一个对象.因为在Python中,无论你把对象做为参数传递, ...