设计模式3.9 桥接模式
2018-12-02 本文已影响2人
卢卡斯哔哔哔
点击进入我的博客
桥接模式是将抽象化与实现化解耦,使两者可以独立地变化。桥接模式有助于理解面向对象的设计原则,包括开闭原则以及组合聚合复用原则。
3.9.1 桥接模式结构
桥接模式这个系统含有两个等级结构
- 由抽象化角色和修正抽象化角色组成的抽象化等级结构。
- 由实现化角色和两个具体实现化角色所组成的实现化等级结构。
桥接模式所涉及的角色
- 抽象化(Abstraction)角色:抽象化给出的定义,并保存一个对实现化对象的引用。
- 修正抽象化(Refined Abstraction)角色:扩展抽象化角色,改变和修正父类对抽象化的定义。
- 实现化(Implementor)角色:这个角色给出实现化角色的接口,但不给出具体的实现。必须指出的是,这个接口不一定和抽象化角色的接口定义相同,实际上,这两个接口可以非常不一样。实现化角色应该只给出底层操作,而抽象化角色应该只给出基于底层操作的更高一层的操作。
- 具体实现化(Concrete Implementor)角色:这个角色给出实现化角色接口的具体实现。
3.9.2 细节
抽象化、实现化、解耦
抽象化:存在于多个实体中的共同的概念性联系;通过忽略一些信息,把不同的实体当作相同的实体来对待。
实现化:抽象化给出的具体实现就是实现化。一个类的实例就是这个类的实现化,一个子类就是它超类的实现化。
解耦:耦合就是两个实体的某种强关联,把它们的强关联去掉就是解耦。
强关联与弱关联:所谓强关联,就是在编译期已经确定的,无法在运行期动态改变的关联;所谓弱关联,就是可以动态地确定并且可以在运行期动态地改变的关联。继承是强关联,而聚合关系是弱关联。
核心理解
桥接模式中的脱耦,就是在抽象化和实现化之间使用组合关系而不是继承关系,从而使两者可以相对独立的变化。
优点
- 实现抽象化和实现化的分离。
- 提高了代码的扩展能力。
- 实现细节对客户透明。
缺点
- 桥接模式的引入会增加系统的理解与设计难度
- 由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
使用场景
- 如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。
- 抽象化角色和实现化角色可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合。
- 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
- 虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者。
- 对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用
Java例子
大多数的驱动器(Driver)都是桥接模式的应用,使用驱动程序的应用系统就是抽象化角色,而驱动器本身扮演实现化角色。
JDBC驱动器
3.9.3 发送消息的案例
- 下面案例中,
SendMsg
及其子类是按照发送消息的方式进行扩展的;而Send
是按照发送消息的时间进行扩展的,两者互不影响。 -
Send
持有类一个SendMsg
对象,并可以使用此对象的方法。
// Implementor角色
interface SendMsg {
void sendMsg();
}
// Concrete Implementor角色
class EmailSendMsg implements SendMsg {
@Override
public void sendMsg() {
System.out.println("Send Msg By Email");
}
}
// Concrete Implementor角色
class WeChatSendMsg implements SendMsg {
@Override
public void sendMsg() {
System.out.println("Send Msg By WeChat");
}
}
// Abstraction 角色
abstract class Send {
protected SendMsg sendMsg;
public Send(SendMsg sendMsg) {
this.sendMsg = sendMsg;
}
public abstract void send();
}
// Concrete Implementor角色
class ImmediatelySend extends Send {
public ImmediatelySend(SendMsg sendMsg) {
super(sendMsg);
}
@Override
public void send() {
sendMsg.sendMsg();
System.out.println("Send Msg Immediately");
}
}
// Concrete Implementor角色
class DelayedlySend extends Send {
public DelayedlySend(SendMsg sendMsg) {
super(sendMsg);
}
@Override
public void send() {
sendMsg.sendMsg();
System.out.println("Send Msg DelayedlySend");
}
}