桥接模式(Bridge Pattern)
基本介绍
- 桥接模式(Bridge 模式)是指:将实现与抽象放在两个不同的类层次中,使两个层次可以独立改变。是一种结构型设计模式。
- 基于类的最小设计原则,通过使用封装、聚合及继承等行为让不同的类承担不同的职责。它的主要特点是把抽象(Abstraction)与行为实现(Implementation)分离开来,从而可以保持各部分的独立性以及应对他们的功能扩展。
核心要点
处理多层继承结构,处理多维度变化的场景,将各个维度设计成独立的继承结构,使各个维度可以独立的扩展在抽象层建立关联。
实际开发的应用场景
- JDBC驱动程序
- AWT中的Peer架构
- 银行日志管理:
- 格式分类:操作日志、交易日志、异常日志
- 距离分类:本地记录日志、异地记录日志
- 人力资源系统中的奖金计算模块:
- 奖金分类:个人奖金、团体奖金、激励奖金。
- 部门分类:人事部门、销售部门、研发部门。
- OA系统中的消息处理:
- 业务类型:普通消息、加急消息、特急消息
- 发送消息方式:系统内消息、手机短信、邮件
桥接模式UML类图
UML类图分析
- 抽象类
Abstraction
维护了Implementor
/ 即它的实现类ConcreteImplementorA
…, 二者是聚合关系,Abstraction
充当桥接类。 Reflection
: 是Abstraction
抽象类的子类。继承父类Abstraction
后,如果需求比较复杂,也可以继续提炼抽象类。Implementor
: 行为的接口。ConcreteImplementorA /B
:可以继承Implementor
行为的接口,对接口再次进行封装;也可以直接实现接口。- 利用这种桥接的关系,完美的实现了各个维度维度可以独立扩展,不同维度间也可以产生关联。
实例分析
以商城系统的商品为例,在场景中一般有两个变化的维度:商品类型和商品品牌
这里以电脑为例:电脑类型和电脑品牌
传统方式实现
一般会采用多继承的方式来实现,如下图
传统方式实现的代码就不具体实现,比较简单:
Computer
父类,定义电脑的公共属性和功能。- 定义
Desktop
、Laptop
、Pad
等电脑类型继承Computer
父类 - 每个类型下面,每个品牌都继承其电脑类型,如:
DellDesktop
继承Desktop
,DellLaptop
继承Laptop
,DellPad
继承Pad
。会产生非常多的类。
分析
扩展性问题(类个数膨胀问题) :
- 如果要增加一个新的电脑类型:智能手机,则要增加各个品牌下面的类。
- 如果要增加一一个新的品牌,也要增加各种电脑类型的类。
违反单一-职责原则:
- 一个类,有两个引起这个类变化的原因。
- 当我们增加手机样式时,要同时增加所有品牌的手机,这样增加了代码维护成本.
桥接模式实现
UML类图
代码实现
1.品牌维度
品牌接口
public interface Brand {
void sale();
}
具体品牌实现
联想
class Lenovo implements Brand {
@Override
public void sale() {
System.out.println("销售联想电脑");
}
}
戴尔
class Dell implements Brand {
@Override
public void sale() {
System.out.println("销售Dell电脑");
}
}
神州
class Shenzhou implements Brand {
@Override
public void sale() {
System.out.println("销售神舟电脑");
}
}
2.品牌类型维度
抽象父类
传入品牌接口,维护聚合关系
public abstract class Computer {
//传入品牌接口,维护聚合关系
protected Brand brand;
public Computer(Brand b) {
this.brand = b;
}
public void sale(){
brand.sale();
}
}
电脑类型
台式机
class Desktop extends Computer {
public Desktop(Brand b) {
super(b);
}
@Override
public void sale() {
super.sale();
System.out.println("销售台式机");
}
}
笔记本
class Laptop extends Computer {
public Laptop(Brand b) {
super(b);
}
@Override
public void sale() {
super.sale();
System.out.println("销售笔记本");
}
}
3.客户端调用
public class Client {
public static void main(String[] args) {
//销售联想的笔记本电脑
Computer c = new Laptop(new Lenovo());
c.sale();
System.out.println("----------");
//销售神舟的台式机
Computer2 c2 = new Desktop(new Shenzhou());
c2.sale();
}
}
执行结果
销售联想电脑
销售笔记本
----------
销售神舟电脑
销售台式机
桥接模式小结
优势
- 实现了抽象和实现部分的分离,从而极大的提供了系统的灵活性,让抽象部分和实现部分独立开来,这有助于系统进行分层设计,从而产生更好的结构化系统。
- 对于系统的高层部分,只需要知道抽象部分和实现部分的接口就可以了,其它的部分由具体业务来完成。
- 桥接模式可以取代多层继承的方案。 多层继承违背了单一职责原则,复用性较差,类的个数也非常多。桥接模式可以极大的减少子类的个数,从而降低管理和维护的成本。
- 桥接模式极大的提高了系统可扩展性,在两个变化维度中任意扩展一
个维度,都不需要修改原有的系统,符合开闭原则。
局限性
- 桥接模式的引入增加了系统的理解和设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计和编程。
- 桥接模式要求正确识别出系统中两个独立变化的维度(抽象、和实现),因此其使用范围有一定的局限性,即需要有这样的应用场景。