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. 概述 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度 ...
随机推荐
- PCA人脸识别
人脸数据来自http://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html 实现代码和效果如下.由于图片数量有限(40*10),将原 ...
- MySQL : interactive_timeout v/s wait_timeout
Most of the database intensive applications are worring about the default values of these variables ...
- 20 款超棒免费的 Bootstrap 管理和前端模板
http://www.oschina.net/news/62506/20-best-free-bootstrap-admin-and-frontend-templates-2015
- 022. ASP.NET为DataSet中数据集添加关系及动态创建主子表和添加主子表关系
protected void Page_Load(object sender, EventArgs e) { string connectionString = "server=.;data ...
- oracle参数与启停
oracle随系统启动而启动 cs65-64桌面版orcle-11.2.0.4 启动监听器,后台进程,OEM. 注意: 如果只做一和三,只能启动后台进程,监听器不启动,如果只做二和三,只能启动监听器, ...
- unity 4 Please check your configuration file and verify this type name.
The problem is in you config file. You are mixing two concepts with some incorrect syntax. The <a ...
- Exploring the Angular 1.5 .component() method
Angular 1.5 introduced the .component() helper method, which is much simpler than the.directive() de ...
- Html.BeginForm())与Ajax.BeginForm()
一.@using (Html.BeginForm())参数示例 1.指定表单提交方式和路径等 @using (Html.BeginForm("Index", "Home ...
- How to send Email using C#
try { MailMessage mail = new MailMessage(); SmtpClient SmtpServer = new SmtpClient("smtp.gmail. ...
- ORACLE 包[转]
包的作用: 包可以将任何出现在块声明的语句 ( 过程 , 函数 , 游标 , 游标 , 类型 , 变量 ) 放于包中 , 相当于一个容器 .使用包的好处不仅仅是程序的分组管理,还可以使用包中的程序重载 ...