欢迎大家提出意见,一起讨论!
转载请标明是引用于 http://blog.youkuaiyun.com/chenyujing1234
例子代码:(编译工具:Eclipse)
参考书籍: <<软件秘笈-----设计模式那点事>>
1、模式定义
桥接模式(Bridge Pattern), 的用意是“将抽象化与实现化脱耦,使得二者可以独立地变化”。
1、1 脱耦
所谓的耦合,就是两个实体的行为的某种强关联。而将它们的强关联去掉,就是耦合的解脱,或脱耦。
2、一般化分析
本模式中我们介绍开关和电灯的例子。
在示例中出现以下角色:
(1)开关
(2)电灯
(3)电线
开关控制电灯,也就是电灯是受开关控制的。开关接通电源,电灯才能亮;开关断开,电灯也就灭了。
这样看来开关应该是一个基类,类中含有开灯、关灯、照明等抽像方法;然后电灯继承开关基类,具体实现开灯、关灯、照明等方法。
3、一般化实现
3、1 建立抽象开关
新建抽象开关基类"AbstractSwitch" 。 该类中存在三个抽象方法:打开开关、照明、关闭开关,还有提供给外部调用的开灯照明方法。
三个抽象方法由子类(电灯)来实现,makeLight方法则是提供给外部应用调用的方法。
/**
* 开关基类
*
* @author
*
*/
public abstract class AbstractSwitch
{
// 打开开关
public abstract void turnOn();
// 照明
public abstract void light();
// 关闭开关
public abstract void turnOff();
// 开灯照明
public final void makeLight()
{
this.turnOn();
this.light();
this.turnOff();
}
}
3、2 电灯实现
3、2、1 白炽灯实现 ---- IncandescentLight
/**
* 白炽灯
*
* @author
*
*/
public class IncandescentLight extends AbstractSwitch {
// 照明方法实现
@Override
public void light() {
System.out.println("白炽灯照明!");
}
// 关闭开关方法 实现
@Override
public void turnOff() {
System.out.println("白炽灯关闭了...");
}
// 打开开关方法实现
@Override
public void turnOn() {
System.out.println("白炽灯打开了...");
}
}
3、2、2 水晶灯实现 ---- CrystalLight
同样继承AbstractSwitch类,实现三个抽象类。不过在水晶灯中扩展一个功能:遥控开灯。
/**
* 水晶灯
*
* @author
*
*/
public class CrystalLight extends AbstractSwitch {
// 照明方法实现
@Override
public void light() {
System.out.println(" 水晶灯照明!");
}
// 关闭开关方法 实现
@Override
public void turnOff() {
System.out.println(" 水晶灯关闭了...");
}
// 打开开关方法实现
@Override
public void turnOn() {
System.out.println(" 水晶灯打开了...");
}
/**
* 使用遥控开关控制开灯
*
* @param operColor
* 灯颜色
*/
public final void makeRemoteLight(int operColor) {
// 打开开关 接通电流
this.turnOn();
// 照明
this.light();
String color = "";
switch (operColor) {
case 1:
color = "暖色";
break;
case 2:
color = "蓝色";
break;
case 3:
color = "红色";
break;
default:
color = "白色";
break;
}
System.out.println(" ...现在是" + color + "!");
// 关闭开关 关闭电流
this.turnOff();
}
}
3、3 客户端测试
/**
* 客户端应用程序
*
* @author
*
*/
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
// 白炽灯 实例
AbstractSwitch light = new IncandescentLight();
// 水晶灯 实例
CrystalLight light2 = new CrystalLight();
System.out.println("-- 一般开关 -- ");
// 一般开关
light.makeLight();
System.out.println("\n-- 遥控开关 -- ");
// 遥控开关
light2.makeRemoteLight(1);
}
}
大家可以看到,要想使用水晶灯的遥控功能就必须创建水晶水晶灯实例对象,不能使用超级类型。
因为超类中没有遥控的功能。
3、4 对于扩展功能的思考
如果现在我们想要用遥控开关遥控白炽灯,该怎么办呢?
有一个方法是再创建一个新类,这样开销太大了。白炽灯是有的,遥控开关也是有的,为什么还要再创建一个类呢?
问题出在我们一开始的设计思路就是错误的,不应该使用继承,因为继承使开关和电灯关联得太强了,也就是一个开关控制一种灯,
要想更换其他种类的电灯必须配备相应的开关才行。
4、 桥接模式分析方法
其实,开关和电灯是完全分开的两个部分,是彼此独立的工作,不应该因为对方的变换而受影响。
这时要使用对象组合的方式,将开关与电灯的强关联变为弱关联。
我们可以看到开关和电灯不再是继承关联关系,而是变为聚合的弱关联关系。
5、 开关与电灯的桥接模式实现
5、1 创建电灯接口
/**
* 电灯接口
*
* @author
*
*/
public interface ILight
{
// 接通电流
public void electricConnected();
// 照明
public void light();
// 电流关闭
public void electricClosed();
}
5、2 创建开关
5、2、1 创建一般开关---- BaseSwitch
建立一般开关"BaseSwitch",该类通过构造方法引入电灯接口,开关照明方法则通过电灯接口实现。
将ILight电灯接口作为开关基类的属性使用,这就是聚合的方式。而开关基类的开灯照明方法,是委托给ILight电类接口完成的。
/**
* 开关顶层类
*
* @author
*
*/
public class BaseSwitch {
// 使用组合 设置ILight为内部私有属性 此为桥梁
protected ILight light;
// 构造方法将 外部的light类型注入进来
public BaseSwitch(ILight light) {
this.light = light;
}
/**
* 开灯方法
*/
public final void makeLight() {
// 打开开关 接通电流
this.light.electricConnected();
// 照明
this.light.light();
// 关闭开关 关闭电流
this.light.electricClosed();
}
}
5、2、2 创建遥控开关 ---- RemoteControlSwitch
它继承于BaseSwitch类,新增加了遥控开关灯的功能
/**
* 遥控开关 继承BaseSwitch 扩展功能
*
* @author
*
*/
public class RemoteControlSwitch extends BaseSwitch
{
// 构造方法
public RemoteControlSwitch(ILight light)
{
super(light);
}
/**
* 使用遥控开关控制开灯
*
* @param operColor
* 灯颜色
*/
public final void makeRemoteLight(int operColor)
{
// 打开开关 接通电流
this.light.electricConnected();
// 照明
this.light.light();
String color = "";
switch (operColor)
{
case 1:
color = "暖色";
break;
case 2:
color = "蓝色";
break;
case 3:
color = "红色";
break;
default:
color = "白色";
break;
}
System.out.println(" ...现在是" + color + "!");
// 关闭开关 关闭电流
this.light.electricClosed();
}
}
5、3 电灯实现
5、3、1 白炽灯实现 ---- IncandescentLight
/**
* 白炽灯 实现
*
* @author
*
*/
public class IncandescentLight implements ILight
{
// 电流关闭
public void electricClosed()
{
System.out.println("白炽灯被关闭了...");
}
// 接通电流
public void electricConnected()
{
System.out.println("白炽灯被打开了...");
}
// 照明
public void light()
{
System.out.println("白炽灯照明!");
}
}
5、3、2 水晶灯实现 ---- CrystalLight
/**
* 水晶灯 实现
*
* @author
*
*/
public class CrystalLight implements ILight
{
// 电流关闭
public void electricClosed()
{
System.out.println("水晶灯被关闭了...");
}
// 接通电流
public void electricConnected()
{
System.out.println("水晶灯被打开了...");
}
// 照明
public void light()
{
System.out.println("水晶灯照明!");
}
}
5、4 客户端测试
5、4、1 一般化测试
/**
* 客户端应用程序
*
* @author
*
*/
public class ClientForBridge {
/**
* @param args
*/
public static void main(String[] args) {
// 白炽灯 实例
ILight incandescentLight = new IncandescentLight();
// 水晶灯 实例
ILight crystalLight = new CrystalLight();
// 一般开关
System.out.println("-- 一般开关 -- ");
BaseSwitch switch1 = new BaseSwitch(incandescentLight);
switch1.makeLight();
System.out.println("\n-- 遥控开关 -- ");
// 遥控开关
RemoteControlSwitch remoteControlSwitch = new RemoteControlSwitch(
crystalLight);
remoteControlSwitch.makeRemoteLight(1);
}
}
同样,我们实现了用开关控制电灯的行为.
-- 一般开关 --
白炽灯打开了...
白炽灯照明!
白炽灯关闭了...
-- 遥控开关 --
水晶灯打开了...
水晶灯照明!
...现在是暖色!
水晶灯关闭了...
5、4、2 让遥控开关遥控白炽灯
将
// 遥控开关
RemoteControlSwitch remoteControlSwitch = new RemoteControlSwitch(
crystalLight);
修改为
// 遥控开关
RemoteControlSwitch remoteControlSwitch = new RemoteControlSwitch(
incandescentLight);
即可.
6、 设计原则
6、1 尽量使用对象聚合弱关联,避免使用继承强关联。
桥接模式中类的抽象及实现都应该能以通过生成子类的方法加以扩充,我们也不必担心软件系统的升级与扩展会给原系统造成不稳定。
6、2 抽象化与实现化脱耦
7、 使用场合
(1)不希望在抽象类和它的实现部分之间有一个固定的绑定关系;
(2)类的抽像及实现都应该可以通过生成子类的方法加以扩充;
(3)对一个抽象的实现部分的修改应对客户不产生影响。
桥接模式,是连接功能部分和实现部分的设计模式,它的用意是把实现和它的接口分开,以便它们可以独立地变化。
桥接模式是在两种层次间扮演彼此沟通的桥梁,它把不同层次分开。如果想新增功能,可以在功能层次(eg:开关)上增加类,根本不需要修改实现类层次;
并且增加功能可以通过实现来使用。