11.结构型 - 桥接模式 (Bridge Pattern)
桥接模式 (Bridge Pattern)
景区卖票的问题
一般去景区游玩,买门票时针对儿童、老人、军人、医护人员或其他特定人群会有一定的优惠:比如儿童6折,老人5折
假如有A、B两个景区,A景区门票原价100,B景区门票原价150。那么,这两个景区的儿童票和老人票如下
| A景区儿童票 | A景区老人票 | B景区儿童票 | B景区老人票 |
|---|
平面化的思维实现是每种组合一个计算类, UML 如下:

假如后续有针对军人、医护人员的优惠该怎么扩展?你可能会说再增加对应的类不就行了
确实可以,但是如果是又增加了C景区、D景区呢,这时候增加的就不只是一两个类了,他们是一个组合关系
桥接模式的解决方式
增加一个维度的概念: 这里的景区可以进行抽象为一个维度(Tickets) , 老人和儿童也可以抽象为一个维度(People)

代码实例
1.景区维度及实现
public interface Tickets {
int getMoney();
}
// <!> A 景区门票
public class ATickets implements Tickets{
final BigDecimal ticketsBigDecimal = new BigDecimal("100"); // a景区门票原价100
private People people;
public ATickets(People people) {
this.people = people;
}
@Override
public int getMoney() {
String sale = people.getSale(); // 获得人员的折扣
BigDecimal saleBigDecimal = new BigDecimal(sale); // java小数计算会丢失精度,要用BigDecimal来计算
return ticketsBigDecimal.multiply(saleBigDecimal).intValue(); // 原价门票乘以折扣
}
}
// <!> B 景区门票
public class BTickets implements Tickets{
final BigDecimal ticketsBigDecimal = new BigDecimal("100"); // B景区门票原价150
private People people;
public ATickets(People people) {
this.people = people;
}
@Override
public int getMoney() {
String sale = people.getSale(); // 获得人员的折扣
BigDecimal saleBigDecimal = new BigDecimal(sale); // java小数计算会丢失精度,要用BigDecimal来计算
return ticketsBigDecimal.multiply(saleBigDecimal).intValue(); // 原价门票乘以折扣
}
}
2.人员维度及实现
public interface People {
String getSale();
}
public class Children implements People {
@Override
public String getSale() {
return "0.6"; //儿童票6折
}
}
public class OlderPeople implements People {
@Override
public String getSale() {
return "0.5"; // 老人票5折
}
}
3.测试
public static void main(String[] args) {
People children = new Children();
People olderPeople = new OlderPeople();.
Tickets aTickets = new ATickets(children);
System.out.println("A景区儿童票=" + aTickets.getMoney());
Tickets bTikcets = new BTickets(olderPeople);
System.out.println("B景区老人票=" + bTikcets.getMoney());
}
in short 把每个功能, 每个需求都用平面化的思维实现的话, 就是组合数的复杂度; 改造成一个主对象(主维度), 通过组合的方式附加功能需求(副维度)
注意: 应该只有两个维度对象, 不然就会无限膨胀!
桥接模式总结
关键角色
桥接模式原理的核心是: 首先有要识别出一个类所具有的的两个独立变化维度, 将它们设计为两个独立的继承等级结构, 为两个维度都提供抽象层,并建立抽象耦合. 总结一句话就是: 抽象角色引用实现角色
- 主维度
- 副维度
桥接模式优缺点
桥接模式的优点:
- 分离抽象接口及其实现部分.桥接模式使用"对象间的关联关系"解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化.
- 在很多情况下,桥接模式可以取代多层继承方案.多层继承方案违背了单一职责原则,复用性差,类的个数多.桥接模式很好的解决了这些问题.
- 桥接模式提高了系统的扩展性,在两个变化维度中任意扩展一个维度都不需要修改原有系统,符合开闭原则.
桥接模式的缺点:
- 桥接模式的使用会增加系统的理解和设计难度,由于关联关系建立在抽象层,要求开发者一开始就要对抽象层进行设计和编程, 不符合高内聚原则
- 桥接模式要求正确识别出系统中的两个独立变化的维度,因此具有一定的局限性,并且如果正确的进行维度的划分,也需要相当丰富的经验.
桥接模式使用场景
-
需要提供平台独立性的应用程序时。 比如,不同数据库的 JDBC 驱动程序、硬盘驱动程序等。
-
需要在某种统一协议下增加更多组件时。 比如,在支付场景中,我们期望支持微信、支付宝、各大银行的支付组件等。这里的统一协议是收款、支付、扣款,而组件就是微信、支付宝等。
-
基于消息驱动的场景。 虽然消息的行为比较统一,主要包括发送、接收、处理和回执,但其实具体客户端的实现通常却各不相同,比如,手机短信、邮件消息、QQ 消息、微信消息等。
-
拆分复杂的类对象时。 当一个类中包含大量对象和方法时,既不方便阅读,也不方便修改。
-
希望从多个独立维度上扩展时。 比如,系统功能性和非功能性角度,业务或技术角度等。

浙公网安备 33010602011771号