From e72318adb46fed5dbdb8920680a3400a931cca0e Mon Sep 17 00:00:00 2001
From: ascoders <576625322@qq.com>
Date: Sun, 15 Nov 2020 16:37:09 +0800
Subject: [PATCH] 173
---
...45\346\250\241\345\274\217\343\200\213.md" | 111 ++++++++++++++++++
1 file changed, 111 insertions(+)
create mode 100644 "173.\347\262\276\350\257\273\343\200\212\350\256\276\350\256\241\346\250\241\345\274\217 - Bridge \346\241\245\346\216\245\346\250\241\345\274\217\343\200\213.md"
diff --git "a/173.\347\262\276\350\257\273\343\200\212\350\256\276\350\256\241\346\250\241\345\274\217 - Bridge \346\241\245\346\216\245\346\250\241\345\274\217\343\200\213.md" "b/173.\347\262\276\350\257\273\343\200\212\350\256\276\350\256\241\346\250\241\345\274\217 - Bridge \346\241\245\346\216\245\346\250\241\345\274\217\343\200\213.md"
new file mode 100644
index 00000000..830df814
--- /dev/null
+++ "b/173.\347\262\276\350\257\273\343\200\212\350\256\276\350\256\241\346\250\241\345\274\217 - Bridge \346\241\245\346\216\245\346\250\241\345\274\217\343\200\213.md"
@@ -0,0 +1,111 @@
+# Bridge(桥接模式)
+
+Bridge(桥接模式)属于结构型模式,是一种解决继承后灵活拓展的方案。
+
+**意图:将抽象部分与它的实现部分分离,使它们可以独立地变化。**
+
+桥接模式比较难理解,我会一步步还原该设计模式的思考,让你体会这个设计模式是如何一步一步被提炼出来的。
+
+## 举例子
+
+如果看不懂上面的意图介绍,没有关系,设计模式需要在日常工作里用起来,结合例子可以加深你的理解,下面我准备了三个例子,让你体会什么场景下会用到这种设计模式。
+
+### 汽车生产线改造为新能源生产线
+
+汽油车与新能源汽车的生产流程有很大相似之处,那么汽油车生产线能否快速改造为新能源汽车生产线呢?
+
+如果汽油车生产线没有将内部实现解耦,只把生产汽油车的各部分独立了出来,对新能源车生产线是没什么用处的,但如果汽油车生产线提供了更底层的能力,比如加装轮胎,加装方向盘,那么这些步骤是可以同时被汽油车与新能源车所共享的。
+
+在设计汽油车生产线时,就将生产过程与汽油车解耦,使其可以快速运用到新能源汽车的生产,这就是桥接模式的一种运用。
+
+### 窗口(Window)类的派生
+
+假设存在一个 Window 窗口类,其底层实现在不同操作系统是不一样的,假设对于操作系统 A 与 B,分别有 AWindow 与 BWindow 继承自 Window,现在要做一个新功能 ManageWindow(管理器窗口),就要针对操作系统 A 与 B 分别生成 AManageWindow 与 BManageWindow,这样显然不容易拓展。
+
+无论我们新增支持 C 操作系统,还是新增支持一个 IconWindow,类的数量都会成倍提升,因为我们所做的 AMangeWindow 与 BMangeWindow 同时存在两个即以上的独立维度,这使得增加维度时,代码变得很冗余。
+
+### 适配多个搭建平台的物料
+
+做前端搭建平台时,经常出现一些物料(组件)因为固化了某个搭建平台的 API,因此无法迁移到另一个搭建平台,如果要迁移,就需要为不同的平台写不同的组件,而这些组件中大部分 UI 逻辑都是一样的,这使得产生大量代码冗余,如果再兼容一个新搭建平台,或者为已有的 10 个搭建平台再创建一个新组件,工作量都是写一个组件的好几倍。
+
+## 意图解释
+
+**意图:将抽象部分与它的实现部分分离,使它们可以独立地变化。**
+
+“抽象” 部分与 “实现” 部分分离,这句话看起来很像接口与实现。确实,如果 “抽象” 指的是 接口(Interface),而 “实现” 指的是 类(Class) 的话,这就是简简单单的 `class MyWindow implements Window` 类实现过程而已。
+
+但后半句话 “使它们可以独立地变化” 会让你难以和前半句联系起来,如果说 “抽象” 不变,“实现” 可以随意改变还好理解,但反过来就难以解释了。
+
+**其实桥接模式中,抽象指的是一种接口(Abstraction),实现指的也是一种接口(Implementor),其中 Implementor 并不是直接实现了 Abstraction 定义的接口,而是提供更底层的方法,使 Abstraction 可以基于它们封装出自己的接口实现。**
+
+这样一来,Abstraction 的接口可以随意变化,毕竟调用的是 Implementor 提供函数的组合,只要 Implementor 提供的功能全面,Implementor 可以不变;相应的,Implementor 的实现也可以随意变化,只要提供的底层函数不变,就不影响 Abstraction 对其的使用。
+
+上面举的三个例子都是这样,我们应该把汽油车生产线的标准与通用汽车生产线标准分离、将具体功能窗口与适配不同操作系统的基础 GUI 能力隔离、将组件功能与平台功能隔离,只有做到了抽象部分与实现部分的隔离,才可以通过组合满足更多场景。
+
+## 结构图
+
+
+
+- Abstraction:定义抽象类的接口。
+- RefinedAbstraction:扩充 Abstraction。
+- Implementor:定义实现类的接口,该接口可以与 Abstraction 接口不一致。
+- ConcreteImplementor:实现 Implementor 接口并定义它的具体实现。
+
+抽象部分就是 Abstraction,实现部分就是 Implementor,在这个结构图中,它们是分离的,可以各自独立变化的,桥接模式,就是指 `imp` 这个桥,通过 Implementor 实现 Abstraction 接口,就算是桥接上了,这种组合的桥接相比普通的类实现更灵活,更具有拓展性。
+
+## 代码例子
+
+对于完全版桥接模式,Implementor 可以有多套实现,Abstraction 不需关心具体用的是哪一种实现,而是通过抽象工厂方式封装。下面举一个简单版的例子。
+
+下面例子使用 typescript 编写。
+
+```typescript
+class Window {
+ private windowImp: WindowImp
+
+ public drawBox() {
+ // 通过画线生成 box
+ this.windowImp.drawLine(0, 1)
+ this.windowImp.drawLine(1, 1)
+ this.windowImp.drawLine(1, 0)
+ this.windowImp.drawLine(0, 0)
+ }
+}
+
+// 拓展 window 就非常容易
+class SuperWindow extends Window {
+ public drawIcon {
+ // 通过自定义画线
+ this.windowImp.drawLine(0, 5)
+ this.windowImp.drawLine(3, 9)
+ }
+}
+```
+
+桥接模式的精髓,通过上面的例子可以这么理解:
+
+`Window` 的能力是 `drawBox`,那继承 `Window` 容易拓展 `drawIcon` 吗?默认是不行的,因为 `Window` 并没有提供这个能力。经分析可以看出,划线是一种基础能力,不应该与 `Window` 代码耦合,因此我们将基础能力放到 `windowImp` 中,这样 `drawIcon` 也可以利用其基础能力画线了。
+
+## 弊端
+
+不要过度抽象,桥接模式是为了让类的职责更单一,维护更便捷,但如果只是个小型项目,桥接模式会增加架构设计的复杂度,而且不正确的模块拆分,把本来关联的逻辑强制解耦,在未来会导致更大的问题。
+
+另外桥接模式也有简单与复杂模式之分,只有一种实现的场景就不要用抽象工厂做过度封装了。
+
+## 总结
+
+桥接模式让我们重新审视类的设计是否合理,把类中不相关,或者说相互独立的维度抽出去,由桥接模式做桥接的方式使用,这样会使每个类功能更内聚,代码量更少更清晰,组合能力更强大,更容易做拓展。
+
+下图做了一个简单的解释:
+
+
+
+> 讨论地址是:[精读《设计模式 - Bridge 桥接模式》· Issue #280 · dt-fe/weekly](https://github.com/dt-fe/weekly/issues/280)
+
+**如果你想参与讨论,请 [点击这里](https://github.com/dt-fe/weekly),每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。**
+
+> 关注 **前端精读微信公众号**
+
+
+
+> 版权声明:自由转载-非商用-非衍生-保持署名([创意共享 3.0 许可证](https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh))