设计模式之桥接模式(Bridge)
注:本文不属于原创,而是根据原文重新整理,原文是:我给媳妇解释设计模式:第一部分
设计模式不是基于理论发明的。相反,总是先有问题场景,再基于需求和情景不断演化设计方案,最后把一些方案标准化成“模式”。所以,我们讨论每一个设计模式时,要尽量用生活中的真实问题来理解和分析。然后尝试一步步地阐述设计,并以一个能匹配某些模式的设计收尾。
设计问题与解决方案
先让我们考虑一下下面的情况:
我们的家里都有家用电器(比如电灯和风扇),他们都是由开关控制。 任何时候,你都可以在不改变其他东西的情况下做一些事。你可以在不更换开关的情况下换掉灯泡,也可以在不接触灯泡或者风扇的情况下更换开关,甚至可以在不接触开关的情况下,把灯泡和风扇的开关互换。
灯泡和风扇
不同类型的开关
当不同的事物联系到一起时,他们应该在一个可以变更或者可以替换的系统中以便不相互影响,或者影响尽可能的小。这样让你更为方便、成本最小地去管理你的系统。可以想象,如果你要换一个你房间里的灯泡得要求你把开关也换了,你会考虑在你房子里使用这样的一个系统吗? 当然不会。 现在,让我们想一下电灯或者电风扇是怎样和开关联系起来以便更换其中一个而不会影响到其他的。当然是电线啦。 是电线以及其他的电工手段把电灯/电风扇与开关连接起来。我们可以把这概括为沟通不同系统的桥梁。基本思想是,一个事物不能直接连接另一个事物。当然,他们能够通过一些桥梁或接口连接起来。在软件世界里,我们称之为“松耦合”。
现在,我们来尝试理解一些类似电灯/电风扇与开关类似的关键问题,同时尝试理解是怎样设计和关联它们的。
在我们的列子里,有一些开关,这些类似普通的开关、有不同的花式开关可能有不同的种类,但是,一般情况下,他们就是开关。同时,每个开关都能开和关。
这样的话,我们就会得到如下的Switch基类:
public class Switch
{
public void On()
{
// 开关有一个“开”的按钮
}
public void Off()
{
// 开关有一个“关”的按钮
}
}
同时,我们可能也需要一些特定类型的开关,譬如正常的开关、不同花式的开关等等。同样的我们扩展Switch类来实现FancySwitch和NormalSwitch:
public class NormalSwitch : Switch
{
} public class FancySwitch : Switch
{
}
这两个特定的开关类可能用于它们自己特有的行为和特征,但是到目前为止,我们还是保持它们现在的简单形式。
现在,如何处理风扇和灯呢?
按照面向对象设计原则中的封闭原则,我认为我们需要试着在任何可能的地方做抽象处理。
电扇和电灯情况有点不一样,它们两个不是同一种东西。对于不同的开关,我们可以用同一个基本的Switch类,但对于电扇和电灯就不大合适了,感觉用接口会更合适一点。因为,从大体上讲,它们都算是电器,那么我们可以就定义一个接口: IElectricalEquipment,用它来抽象电扇和电灯。
那么,所有电器都有一些共性,可以被打开和关闭。那么这个接口就可以是:
public interface IElectricalEquipment
{
void PowerOn(); // 每个电器都能够被打开
void PowerOff(); // 每个电器都能够被关闭
}
好了,现在我们还缺一座桥。在现实世界里,桥是电线。在对象的世界里,开关知道怎么开关电器,电器需要用某种方式跟开关连起来。可这里没有电线,我们唯一有的,是封装。
开关并不知道电扇和电灯的存在。它只知道它可以打开或关闭某个电器IElectricalEquipment。那么,也就是说每个Switch应该拥有一个IElectricalEquipment实例。
这里,被封装的实例,也就是IElectricalEquipment,就是这座桥。好,我们来修改一下Switch类,让它把电器封装进去:
public class Switch
{
public IElectricalEquipment equipment
{
get;
set;
}
public void On()
{
// 开关有一个打开的按钮
}
public void Off()
{
// 开关有一个关闭的按钮
}
}
接下来我再定义真正的电器吧。电扇和电灯,总体上都是电器,所以它们应该实现IElectricalEquipment接口。
电扇类:
public class Fan : IElectricalEquipment
{
public void PowerOn()
{
Console.WriteLine("Fan is on");
}
public void PowerOff()
{
Console.WriteLine("Fan is off");
}
}
电灯类:
public class Light : IElectricalEquipment
{
public void PowerOn()
{
Console.WriteLine("Light is on");
}
public void PowerOff()
{
Console.WriteLine("Light is off");
}
}
很好。现在该是接上开关的时候了。开关在打开和关闭的时候,必须能打开和关闭它所连接的电器。
也就是说:
• 当按下开关的打开按钮时,必须打开连接的电器。
• 当按下开关的关闭按钮时,必须关闭连接的电器。
我们想要的功能基本上是这个样子:
static void Main(string[] args)
{
//我们有一些电器,比如风扇、电灯等,因此我们首先要创建它们
IElectricalEquipment fan = new Fan();
IElectricalEquipment light = new Light();
//我们也有一些开关,同样需要创建它们
Switch fancySwitch = new FancySwitch();
Switch normalSwitch = new NormalSwitch(); //让我们将电扇和电扇开关连接起来
fancySwitch.equipment = fan; //现在开关对应了一个设备(电扇),因此可以开关设备。
//下面这个操作将打开电扇
//当然,在开关的这个 On() 方法里面我们必须打开电器。
fancySwitch.On();
//下面这个操作将关闭电扇
fancySwitch.Off(); //现在我们将电灯与风扇的开关连接起来
fancySwitch.equipment = light;
fancySwitch.On(); // 现在它将打开电灯
fancySwitch.Off(); // 现在它将关闭电灯
}
那么,开关的On()方法应该调用电器的TurnOn()方法,而它的Off()方法应该调用电器的TurnOff()方法,Switch类应该是这个样子:
public class Switch
{
public void On()
{
Console.WriteLine("Switch on the equipment");
equipment.PowerOn();
}
public void Off()
{
Console.WriteLine("Switch off the equipment");
equipment.PowerOff();
}
}
这个电扇显示是可以换开关的。而且,反过来也是可以换的,可以不修改电扇和电灯,直接更换开关,例如,我们可以把电灯的开关从FancySwitch换成NormalSwitch:
normalSwitch.equipment = light;
normalSwitch.On(); //It should turn on the Light now
normalSwitch.Off(); //It should be turn off the Light now
看到没,我们可以在不影响任何一方的情况下,改变另一方。这个设计看起来很不错,而且相当的优雅。其实四人帮(GoF)管这个设计叫桥接模式。
一般来说,两个系统不应该直接地互相联接和依赖。相反,他们应该通过抽象来联接或依赖(参见依赖倒置和开闭原则),这样它们就是松耦合的,我们就可以在必要时轻松地修改实现,而不对系统的其它部分造成太大影响。
桥接模式的定义
我们来看一下桥接模式的定义吧:
“把抽象和实现解耦,使得它们可以独立地变化”
桥接模式的类图结构如下:
在我们的例子里,Abstraction是基础的Switch类,RefinedAbstraction是某个具体的开关类(FancySwitch和NormalSwitch),Implementor是IElectricalEquipment接口,ConcreteImplementorA和ConcreteImplementorB分别是Fan和Light类。
桥接模式是所有面向对象设计模式的基础。因为:
• 它能教你如何抽象地思维,这可是OO设计模式的关键。
• 它实现了基本的OOD原则。
• 它很好理解。
• 如果能正确地理解它,学习其它模式就易如反掌了。
设计模式之桥接模式(Bridge)的更多相关文章
- 乐在其中设计模式(C#) - 桥接模式(Bridge Pattern)
原文:乐在其中设计模式(C#) - 桥接模式(Bridge Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 桥接模式(Bridge Pattern) 作者:webabcd 介绍 ...
- 【设计模式】桥接模式 Bridge Pattern
开篇还是引用吕振宇老师的那篇经典的文章<设计模式随笔-蜡笔与毛笔的故事>.这个真是太经典了,没有比这个例子能更好的阐明桥接模式了,这里我就直接盗来用了. 现在市面上卖的蜡笔很多,各种型号, ...
- python 设计模式之桥接模式 Bridge Pattern
#写在前面 前面写了那么设计模式了,有没有觉得有些模式之间很类似,甚至感觉作用重叠了,模式并不是完全隔离和独立的,有的模式内部其实用到了其他模式的技术,但是又有自己的创新点,如果一味地认为每个模式都是 ...
- 二十四种设计模式:桥接模式(Bridge Pattern)
桥接模式(Bridge Pattern) 介绍将抽象部分与它的实现部分分离,使它们都可以独立地变化. 示例有一个Message实体类,对它的操作有Insert()和Get()方法,现在使这些操作的抽象 ...
- [设计模式] 7 桥接模式 bridge
#include<iostream> using namespace std; class AbstractionImp { public: virtual ~AbstractionImp ...
- 设计模式之桥接模式(Bridge)--结构模型
1.意图 将抽象部分与它的实现部分分离,使它们可以独立地变化. 2.适用性 你不希望在抽象和它的实现部分之间有一个固定的绑定关系. 类的抽象与它的实现都应该可以通过子类的方式加以扩展. 抽象部分与实现 ...
- 设计模式 笔记 桥接模式 Bridge
//---------------------------15/04/15---------------------------- //Bridge 桥接模式----对象结构型模式 /* 1:意图:将 ...
- 设计模式之桥接模式(Bridge)
桥接模式与原理:将抽象部分与实现部分分离,使它们都可以独立的变化.最终的结果表现在实现类中.两者之间属于等价关系,即实现部分和抽象部分可以相互交换. 代码如下 #include <iostrea ...
- 结构型设计模式之桥接模式(Bridge)
结构 意图 将抽象部分与它的实现部分分离,使它们都可以独立地变化. 适用性 你不希望在抽象和它的实现部分之间有一个固定的绑定关系.例如这种情况可能是因为,在程序运行时刻实现部分应可以被选择或者切换. ...
- 【设计模式】—— 桥接模式Bridge
前言:[模式总览]——————————by xingoo 模式意图 这个模式使用的并不多,但是思想确实很普遍.就是要分离抽象部分与实现部分. 实现弱关联,即在运行时才产生依赖关系. 降低代码之间的耦合 ...
随机推荐
- Spark源码系列(六)Shuffle的过程解析
Spark大会上,所有的演讲嘉宾都认为shuffle是最影响性能的地方,但是又无可奈何.之前去百度面试hadoop的时候,也被问到了这个问题,直接回答了不知道. 这篇文章主要是沿着下面几个问题来开展: ...
- css3整理--::selection
::selection作用: 当使用鼠标选择文本时,改版被选中文本的背景色和前景色.(默认情况下,window中背景色是深蓝色,前景色是白色.) ::selection语法: /*Mozilla Fi ...
- HiKey连接
http://wiki.lemaker.org/LeMaker_Hikey:FAQ/zh-hans
- strcpy和memcpy的区别
strcpy和memcpy都是标准C库函数,它们有下面的特点.strcpy提供了字符串的复制.即strcpy只用于字符串复制,并且它不仅复制字符串内容之外,还会复制字符串的结束符. 已知strcpy函 ...
- Backbone1.0.0数据验证的变化
0.5.3版本对Model数据验证时,绑定Error就可以了: (function(){ var Model = Backbone.Model.extend({ initialize : functi ...
- [转] VB之Val()函数的使用
在VB中,也许你或多或少会希望得到的数据转换成数字类型,数字类型既可以是整形,单精度,双精度,浮点数,只要是数字类型这个都可以使用,不过此函数只返回字符串中包含的数字,若第一个字符为字母或者非数字字符 ...
- sourceinsight技巧
Source Insight实质上是一个支持多种开发语言(java,c ,c++等等)的编辑器,只不过由于其查找.定位.彩色显示等功能的强大,常被我们当成源代码阅读工具使用. 所以,为了有效的阅读源程 ...
- selenium webdriver (python) 第二版
前言 对于大多软件测试人员来讲缺乏编程经验(指项目开发经验,大学的C 语言算很基础的编程知识)一直是难以逾越的鸿沟,并不是说测试比开发人员智商低,是国内的大多测试岗位是功能测试为主,在工作时间中,我们 ...
- ExtJs创建环境搭建
开发工具Eclipse/MyEclipse. 工具下载:http://pan.baidu.com/s/1sjmiFMH(提供spket和sdk.jsb3, extjs-4.1.1需自己下载) 1. ...
- SQL Server 存储(2/8):理解数据记录结构
在SQL Server :理解数据页结构我们提到每条记录都有7 bytes的系统行开销,那这个7 bytes行开销到底是一个什么样的结构,我们一起来看下. 数据记录存储我们具体的数据,换句话说,它存在 ...