1、桥接模式(Bridge)的定义
桥接模式(Bridge Pattern),又称为柄体(Handle and Body)模式或接口(Interface)模式。将抽象部分与它的实现分离,并不是说让抽象类与其派生类分离,而是用抽象类和它的派生类用来实现自己的对象。(将抽象化(Abstraction)与实现化Implementation)脱耦,使得二者可以独立地变化)
- 从众多的事物中抽取出共同的、本质性的特征,而舍弃其非本质的特征,就是抽象化。例如苹果、香蕉、生梨、 桃子等,它们共同的特性就是水果。得出水果概念的过程,就是一个抽象化的过程。要抽象,就必须进行比较,没有比较就无法找到在本质上共同的部分。共同特征是指那些能把一类事物与他类事物区分开来的特征,这些具有区分作用的特征又称本质特征。因此抽取事物的共同特征就是抽取事物的本质特征,舍弃非本质的特征。 所以抽象化的过程也是一个裁剪的过程。在抽象时,同与不同,决定于从什么角度上来抽象。抽象的角度取决于分析问题的目的。通常情况下,一组对象如果具有相同的特征,那么它们就可以通过一个共同的类来描述。如果一些类具有相同的特征,往往可以通过一个共同的抽象类来描述。
- 抽象化给出的具体实现,就是实现化。一个类的实例就是这个类的实例化,一个具体子类是它的抽象超类的实例化。
- 所谓耦合,就是两个实体的行为的某种强关联。而将它们的强关联去掉,就是耦合的解脱,或称脱耦。在这里,脱耦是指将抽象化和实现化之间的耦合解脱开,或者说是将它们之间的强关联改换成弱关联。
- 所谓强关联,就是在编译时期已经确定的,无法在运行时期动态改变的关联;所谓弱关联,就是可以动态地确定并且可以在运行时期动态地改变的关联。显然,在Java语言中,继承关系是强关联,而聚合关系是弱关联。
- 将两个角色之间的继承关系改为聚合关系,就是将它们之间的强关联改换成为弱关联。因此,桥梁模式中的所谓脱耦,就是指在一个软件系统的抽象化和实现化之间使用聚合关系而不是继承关系,从而使两者可以相对独立地变化。这就是桥梁模式的用意。
2、模式(Bridge)优缺点
桥接模式是一种结构型设计模式。其主要优缺点如下:
优点:
- 抽象和实现的分离;让抽象部分和实现部分独立出来,分别定义接口,这有助于对系统进行分层,从而产生更好的结构化的系统。
- 优秀的扩展能力;桥梁模式使得抽象部分和实现部分可以分别独立地扩展,而不会相互影响,从而大大提高了系统的可扩展性。
- 实现细节对客户透明。
- 单一职责原则。
- 松耦合:继承是一种强耦合关系,子类与父类有非常紧密的依赖关系,父类的任何变化 都会导致子类发生变化。因此才使用桥接模式,使用了桥接模式之后,我们的两个维度就像桥梁一样被链接了起来。体现了松耦合的特性。
缺点:
- 会增加系统的理解与难度。
3、模式(Bridge)适用环境
- 不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统;
- 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展
4、模式(Bridge)的结构
可以看出,这个系统含有两个等级结构:
- 由抽象化角色和修正抽象化角色组成的抽象化等级结构。
- 由实现化角色和两个具体实现化角色所组成的实现化等级结构。
桥接模式包含如下角色:
- 抽象化(Abstraction)角色 :抽象化给出的定义,并保存一个对实现化对象的引用。
- 修正抽象化(RefinedAbstraction)角色 :扩展抽象化角色,改变和修正父类对抽象化的定义。
- 实现化(Implementor)角色 :这个角色给出实现化角色的接口,但不给出具体的实现。必须指出的是,这个接口不一定和抽象化角色的接口定义相同,实际上,这两个接口可以非常不一样。实现化角色应当只给出底层操作,而抽象化角色应当只给出基于底层操作的更高一层的操作。
- 具体实现化(ConcreteImplementor)角色 :这个角色给出实现化角色接口的具体实现。
5、模式(Bridge)应用场景
银行日志管理
- 格式分类 : 操作日志 , 交易日志 , 异常日志
- 距离分类 : 本地记录日志 , 异地记录日志
人力资源系统中的奖金计算模块
- 奖金分类 : 个人奖金 , 团体奖金 , 激励奖金
- 部门分类 : 人事部门 , 销售部门 , 研发部门
OA系统中的消息处理
- 业务类型 : 普通消息 , 加急消息 , 特急消息
- 发送消息类型 : 站内信 , 短信 , 邮箱
6、模式(Bridge)的应用实例
软件抽象类及相应的实现类
//软件类(Abstraction)
public abstract class Soft {
public abstract void run();
}
//RefinedAbstraction
public class Game extends Soft{
@Override
public void run() {
System.out.println("运行手机游戏");
}
}
public class AddressList extends Soft{
@Override
public void run() {
System.out.println("运行通讯录");
}
}
手机品牌抽象类及相应的实现类(Implementor)
public abstract class PhoneBrand {
public Soft soft; //引用了软件类 类似桥梁,将两个抽象类连通
public void setSoft(Soft soft) {
this.soft = soft;
}
public abstract void run();
}
//品牌M
public class BrandM extends PhoneBrand{
@Override
public void run() {
super.soft.run();
System.out.println("品牌M");
}
}
//品牌N
public class BrandN extends PhoneBrand{
@Override
public void run() {
super.soft.run();
System.out.println("品牌N");
}
}
测试类
public class JavaDemo {
public static void main(String[] args) {
PhoneBrand brand1 = new BrandM();
brand1.setSoft(new Game());
brand1.run();
brand1.setSoft(new AddressList());
brand1.run();
PhoneBrand brand2 = new BrandN();
brand2.setSoft(new Game());
brand2.run();
brand2.setSoft(new AddressList());
brand2.run();
}
}
/**
运行手机游戏
品牌M
运行通讯录
品牌M
运行手机游戏
品牌N
运行通讯录
品牌N
*/
评论区