想要上天找仙女?Bridge Pattern 来搭桥

93 阅读3分钟

在中国古代神话中, 有很多仙女下凡与凡人相恋的故事, 比如牛郎-织女, 董永-七仙女, 刘彦昌-三圣母等等, 他们之间都隔着一道银河,想要唠嗑就需要一座桥,今天就介绍一下桥接模式****(Bri****dge Pattern)

目的

![](https://mmbiz.qpic.cn/mmbiz_gif/7QRTvkK2qC5Ae7TL0ribktKWDdib4Lv47xsog4G72hP4TiceEfibZ8KibSDBg2SRNvDzOa8abYBLdQQNRY3tkZMIrfg/640?wx_fmt=gif&tp=webp&wxfrom=5&wx_lazy=1)

将二个变化的维度分离开, 简而言之就是双重策略模式

例子代码

![](https://mmbiz.qpic.cn/mmbiz_gif/7QRTvkK2qC5Ae7TL0ribktKWDdib4Lv47xsog4G72hP4TiceEfibZ8KibSDBg2SRNvDzOa8abYBLdQQNRY3tkZMIrfg/640?wx_fmt=gif&tp=webp&wxfrom=5&wx_lazy=1)

我们假设牛郎想去七仙女和三圣母那儿串门, 这个牛郎又看过(策略模式), 他想到他以后可能还要访问别的仙女(这到底是不是我认识的淳朴牛郎...),

就用策略模式又搭了两座桥(泛型方式请看策略模式文章):

public interface NiuLangVisitStrategy {   String visitGirl();}

牛郎访问织女:

public class NiuLangVisitZhiNvStrategyImpl             implements NiuLangVisitStrategy {@Override   public String visitGirl() {       return "牛郎访问了织女";}}

牛郎访问三圣母:

public class NiuLangVisitSanShengMuStrategyImpl             implements NiuLangVisitStrategy {@Override   public String visitGirl() {       return "牛郎访问了三圣母";}}

牛郎访问七仙女:

public class NiuLangVisitQiXianNvStrategyImpl             implements NiuLangVisitStrategy {@Override   public String visitGirl() {       return "牛郎访问了七仙女";}}
**问题分析**
![](data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==)

我们分析这个情况用策略模式有两个弊端:

一个是类的数量会爆炸性增长;另一个是不利于代码的复用。

一是本来牛郎这个策略是用的非常好的, 但是对董永和刘昌彦不是很好, 这个时候董永也想去串门了, 他又实现了一个 DongyongVisitStrategy 的三个类:

public interface DongYongVisitStrategy {   String visitGirl();}

董永访问织女:

public class DongYongVisitZhiNvStrategyImpl                          implements DongYongVisitStrategy {@Override      public String visitGirl() {              return "董永访问了织女";}}

董永访问七仙女:

public class DongYongVisitQiXianNvStrategyImpl             implements DongYongVisitStrategy {@Override   public String visitGirl() {       return "董永访问了七仙女";}}

董永访问三圣母:

public class DongYongVisitSanShengMuStrategyImpl             implements DongYongVisitStrategy {@Override   public String visitGirl() {       return "董永访问了三圣母";}}

这时候刘昌彦也想去...这就变成 9 个类了, 这用策略模式就有些勉强了, 我们经过一阵复杂的排序组合知识, 预计类的数量是 m(凡人数量)n(仙女数量) 这么多, 这个时候, 如果又下凡了一个仙女, 类的数量就是 44 = 16 个了。

二是如果 "访问了" 三个字在生产环境里是成百上千的代码, 那么重复的代码就会很多, 一旦变更, 需要在多个地方变更。

**桥接模式**
![](data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==)

我们定义找个二个可能变化的维度: A 访问了 B, A 的变化 B 不应该感知, B 的变化 A 也不需要感知

定义二个变化维度的接口:

女孩:

public interface Girl {   String queryName();}

男孩:

public interface Body {   default String action() {       return "访问了";}   default String visitGirl(Girl girl){       return queryName() + action()                     + girl.queryName();}   String queryName();}

实现三个女孩:

public class QiXianNvGirl             implements Girl {@Override   public String queryName() {       return "七仙女";}}public class SanShengMuGirl             implements Girl {@Override   public String queryName() {       return "三圣母";}}public class ZhiNvGirl             implements Girl {@Override   public String queryName() {       return "织女";}}

实现三个男孩:

public class DongYongBody             implements Body {@Override   public String queryName() {       return "董永";}}public class LiuChangYanBody              implements Body {@Override   public String queryName() {       return "刘昌彦";}}public class NiuLangBody             implements Body {@Override   public String queryName() {       return "牛郎";}}

使用:

System.out.println(new NiuLangBody().visitGirl(new ZhiNvGirl()));

我们成功把 m * n 个类 变成了 m + n 个类, 并且代码的可复用性提高了很多。

**桥接模式课后作业**
![](data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==)

1. 使用策略模式的泛型实现文中的例子

2. 增加了杨天佑和云华仙子的情况, 使用策略模式和桥接模式分别实现进行对比

3. 这天, 我们接到产品的需求, 信用贷款遇到 A 优惠卷利息减 3 元, 遇到 B 优惠卷利息打 8 折, 遇到 C 优惠卷利息小于1元的部分打8折, 大于1元的部分减 3 元, 请用策略模式实现

4. 这天, 我们又接到了一个需求, 订单贷款遇到 A 优惠卷手续费减 3 元, 遇到 B 优惠卷利息打 8 折, 遇到 C 优惠卷利息小于1元的部分打8折, 大于1元的部分减 3 元, 请用策略模式和桥接模式分别实现

codog代码狗 wx: