Bridge桥接模式
当我们的功能要在多个维度进行扩展时,各个维度之间可以交叉组合,就可以考虑使用桥接模式。
将抽象部分与实现部分分离,使它们都可以独立的变化。
——《设计模式》GOF
我们看一个实际的例子来理解:
我想发一条短信,首先,我要选择使用哪一种信号(联通、移动、电信);其次,我们要选择发送的内容(文本、附件、音频);最后,我们要选择发送的时间(实时、定时)。
那么,这里有三个维度的变化,每个维度有3、3、2种类型,如果我们使用传统的继承的方式来扩展一个类的功能,那么我们需要一个顶级短信发送类,3种信号类都去继承这个顶级类,3种内容类去继承每一种信号类,2种发送时间类再去继承每一种内容类。
这样我们得到了3*3*2+1=19个类(或者不要顶级类,得到18个类),如果再有其他的扩展维度进来的话,类的个数将不堪设想。
这时我们就可以考虑使用桥接模式,使各个扩展维度之间解耦,使它们相互独立。每个变化的维度都可以抽象成统一的类,由这个维度变化的子类去进行扩展。而各个维度的抽象类之间,可以相互持有各自的引用,从而拥有其他维度的功能。
各个变化维护的抽象类:
public abstract class Message {
private String content;
abstract public void send();
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
public abstract class Signal {
protected Message msg;
public abstract void invoke();
}
各个维度变化的子类:
public class TextMessage extends Message {
@Override
public void send() {
System.out.println("发送【文字】信息:" + this.getContent());
}
}
public class PicMessage extends Message {
@Override
public void send() {
System.out.println("发送【图片】信息:" + this.getContent());
}
}
public class AudioMessage extends Message {
@Override
public void send() {
System.out.println("发送【语音】信息:" + this.getContent());
}
}
public class YiDongSignal extends Signal {
public YiDongSignal(Message msg) {
super();
this.msg = msg;
}
@Override
public void invoke() {
System.out.print("使用【移动】:");
msg.send();
}
}
public class LianTongSignal extends Signal {
public LianTongSignal(Message msg) {
super();
this.msg = msg;
}
@Override
public void invoke() {
System.out.print("使用【联通】:");
msg.send();
}
}
public class DianXinSignal extends Signal {
public DianXinSignal(Message msg) {
super();
this.msg = msg;
}
@Override
public void invoke() {
System.out.print("使用【电信】:");
msg.send();
}
}
客户端调用:
public class Client {
public static void main(String[] args) {
Message msg = new TextMessage();
msg.setContent("Hello World!");
Signal signal = new YiDongSignal(msg);
signal.invoke();
}
}
输出结果:
使用【移动】:发送【文字】信息:Hello World!
上面只扩展了两个维度,如果现在我们要扩展第三个维度--发送时间的话,就可以简单的加几个类就行了:
变化维度抽象类:
public abstract class SendTime {
protected Signal signal;
abstract public void sendMsg();
}
变化维度子类:
public class InstantSendTime extends SendTime{
public InstantSendTime(Signal signal) {
super();
this.signal = signal;
}
@Override
public void sendMsg() {
System.out.print("【实时发送】-->");
this.signal.invoke();
}
}
客户端调用:
public class Client2 {
public static void main(String[] args) {
Message msg = new TextMessage();
msg.setContent("Hello World!");
Signal signal = new YiDongSignal(msg);
SendTime sendTime = new InstantSendTime(signal);
sendTime.sendMsg();
}
}
输出结果:
【实时发送】-->使用【移动】:发送【文字】信息:Hello World!
细心的读者不难发现,在我们客户端调用的时候,有点像Decorator装饰模式。
但它和Decorator是有区别的,Bridge是从多个维度扩展,而Decorator是将多个包装类的功能加在一起,组合成一个多功能的类。(描述不太清楚,后续修改)
可以再看看Decorator装饰模式自己体味区别
Bridge桥接模式的更多相关文章
- C++设计模式-Bridge桥接模式
作用:将抽象部份与它的实现部份分离,使它们都可以独立地变化. 将抽象(Abstraction)与实现(Implementation)分离,使得二者可以独立地变化. 桥接模式号称设计模式中最难理解的模式 ...
- Bridge桥接模式(结构型模式)
现有一个需求,一个游戏系统需要构建不同风格的房屋,暂不考虑其他设计模式,需要能实现在PC端.移动端....等等多个平台的构建.最简单的实现方式如下: /// <summary> /// 房 ...
- 设计模式07: Bridge 桥接模式(结构型模式)
Bridge 桥接模式(结构型模式) 抽象与实现 抽象不应该依赖于实现细节,实现细节应该依赖于抽象. 抽象B稳定,实现细节b变化 问题在于如果抽象B由于固有的原因,本身并不稳定,也有可能变化,怎么办? ...
- Bridge桥接模式(设计模式11)
在没有使用桥接模式: 扩展新问题(类归属膨胀问题) 1增加性的电脑类型,要增加每个品牌下面的类 2如果要增加一个新的电脑品牌,要增加美中电脑类型的类 违背单一职责原则: · 一个类:联想笔记本,有两个 ...
- 一天一个设计模式——Bridge桥接模式
一.概念准备 在理解桥接模式之前,先要理解面向对象程序设计中的两个概念: 类的功能层次结构:假设现在有一个类Something,这个类有一些成员属性和成员方法,但是现有的功能不能满足要求,因此我们想扩 ...
- 设计模式(八):Bridge桥接模式 -- 结构型模式
1. 概述 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度 ...
- 面向对象设计模式纵横谈:Bridge 桥接模式(笔记记录)
桥接模式是一个比较难理解的设计模式,设计和分析的时候也不容易把握,咱们听听“李建忠”老师是怎么来讲的.我们还是从演变的角度来说问题,一步一步的来把问题说清楚.先谈谈“抽象”和“实现”的关系. 抽象与实 ...
- Bridge 桥接模式 MD
桥接模式 简介 将抽象部分与实现部分分离,使它们都可以独立的变化. 业务抽象角色引用业务实现角色,或者说业务抽象角色的部分实现是由业务实现角色完成的 Bridge模式基于类的最小设计原则,通过使用封装 ...
- Bridge - 桥接模式
1. 概述 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度 ...
随机推荐
- Nginx-server_name匹配规则
server_name可为IP/domain/localhost/null等任何字符串(字符串server_name也可以用来匹配),注意各个 server 块的顺序. 1.如果只有一个server, ...
- shell脚本实例-matrix
[Sat Feb 27 17:51:36 1038 /dev/pts/0 192.168.2.250 ~/sh]#cat matrix blue="\033[0;34m" brig ...
- OpenJudge就算概论-统计字符数
/*===================================== 统计字符数 总时间限制: 1000ms 内存限制: 65536kB 描述 判断一个由a-z这26个字符组成的字符串中哪个 ...
- OpenJudge计算概论-单词倒排【把句子内单词的顺序翻转】
/*================================================== 单词倒排 总时间限制: 1000ms 内存限制: 65536kB 描述 编写程序,读入一段英文 ...
- 结合Scikit-learn介绍几种常用的特征选择方法
特征选择(排序)对于数据科学家.机器学习从业者来说非常重要.好的特征选择能够提升模型的性能,更能帮助我们理解数据的特点.底层结构,这对进一步改善模型.算法都有着重要作用. 特征选择主要有两个功能: 减 ...
- java.sql.SQLException: Io 异常: Connection reset
当数据库连接池中的连接被创建而长时间不使用的情况下,该连接会自动回收并失效,但客户端并不知道,在进行数据库操作时仍然使用的是无效的数据库连接,这样,就导致客户端程序报“ java.sql.SQLExc ...
- officetohtml
http://blog.csdn.net/mcpang/article/details/6817643
- PhoneGap原理分析
PhoneGap提供了Native Api的支持(如:重力感应.相机.联系人.文件.地址位置…), 比如要用js获取本机的联系人,可以用: var options = new ContactFindO ...
- SQL SERVER 组内排序
取出每组的第一个 select *from (select * ,RANK ( ) OVER( PARTITION by org order by reportcode asc) PartionNum ...
- 【jmeter】HTTP属性管理器HTTP Cookie Manager、HTTP Request Defaults
Test Plan的配置元件中有一些和HTTP属性相关的元件:HTTP Cache Manager.HTTP Authorization Manager.HTTP Cookie Manager.HTT ...