桥接模式.md 5.0 KB
Newer Older
ツぃ☆ve芜情's avatar
ツぃ☆ve芜情 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
> 本部分内容参见[这里](https://baijiahao.baidu.com/s?id=1639383166201396225&wfr=spider&for=pc)

## 定义

桥接模式(Bridge Pattern),将抽象部分与它的实现部分分离,使它们都可以独立地变化。更容易理解的表述是:实现系统可从多种维度分类,桥接模式将各维度抽象出来,各维度独立变化,之后可通过聚合,将各维度组合起来,减少了各维度间的耦合。

## 示例

我们都去买过手机,手机按照品牌分可以分为华为、小米、OPPO、vivo 等品牌,如果这些手机按照内存分又可以分为 4 G、6 G、8 G等等。假如我们每一种手机都想要玩一下,至少需要 4×3 个。这对我们来说这些手机也太多了,竟然有 12 个,最主要的是手机品牌和内存是放在一起的。现在有这样一种机制,手机牌品商是一个公司,做手机内存的是一个公司,想要做什么手机我们只需要让其两者搭配起来即可。有点类似于全球贸易分工明确的思想,这就是桥接模式,把两个不同维度的东西桥接起来。

从上面的例子我们可以看到,我们的手机可以从两个维度进行变化,一个是品牌,一个是内存。此时我们就可以通过桥接模式将这两个维度分离开来,每一个维度都可以独立扩展。比如说手机品牌,可以又出现了苹果、三星、锤子等等。内存方面又可以生产 10 G、16 G 的了。从专业的角度来看可以这样定义桥接模式:

> 桥接模式是一种很实用的结构型设计模式,如果软件系统中某个类存在两个独立变化的维度,通过该模式可以将这两个维度分离出来,使两者可以独立扩展,让系统更加符合“单一职责原则”。

上面的例子我们画一张类图来表示一下:

![](img/01.jpeg)

基本上意思就是这,也就是我们买手机的时候有两个维度可供我们选择:一个是品牌一个是内存。

(1)Client:指的是我们买手机的人

(2)Abstraction(抽象类):指的是手机抽象类

(3)Refined Abstraction(具体类):指的是具体手机品牌

(4)Implementor:在这里相当于手机的其他组件,内存

(5)Concrete Implementor:具体的内存型号

## 实现

第一步:定义 Implementor,这里定义手机内存接口

```java
public interface Memory {
    void addMemory();
}
```

第二步:定义 Concrete Implementor,这里指具体的内存

内存这里定义了两种一种是 6 G,一种是 8 G

```java
public class Memory6G implements Memory{
    @Override
    public void addMemory() {
        System.out.println("手机安装了6G内存");
    }
}
// ---------------------------------------
public class Memory8G implements Memory{
    @Override
    public void addMemory() {
        System.out.println("手机安装了8G内存");
    }
}
```

第三步:定义 Abstraction 手机抽象类

```java
public abstract class Phone {
    protected Memory phoneMemory;

    public void setPhoneMemory(Memory phoneMemory) {
        this.phoneMemory = phoneMemory;
    }
    public abstract void buyPhone();
}
```

第四步:定义Refined Abstraction(具体的手机品牌)

首先是华为

```java
public class HuaWei extends Phone{
    @Override
    public void buyPhone() {
        phoneMemory.addMemory();
        System.out.println("购买华为手机");
    }
}
```

然后是小米

```java
public class Mi extends Phone{
    @Override
    public void buyPhone() {
        phoneMemory.addMemory();
        System.out.println("购买小米手机");
    }
}
```

第五步:测试一下

```java
public class Client {
    public static void main(String[] args) {
        // 华为8G手机
        System.out.println("====== 华为8G手机 ======");
        HuaWei huaWei = new HuaWei();
        huaWei.setPhoneMemory(new Memory8G());
        huaWei.buyPhone();
        // 小米6G手机
        System.out.println("====== 小米6G手机 ======");
        Mi mi = new Mi();
        mi.setPhoneMemory(new Memory6G());
        mi.buyPhone();
    }
}
```

```
====== 华为8G手机 ======
手机安装了8G内存
购买华为手机
====== 小米6G手机 ======
手机安装了6G内存
购买小米手机
```

从代码就可以看出,购买手机的时候,品牌和内存两个维度是分开的。下面我们分析一下这个桥接模式

## 分析桥接模式

### 为什么使用桥接模式不使用继承呢?

继承是一种强耦合关系,子类与父类有非常紧密的依赖关系,父类的任何变化都会导致子类发生变化。因此才使用桥接模式,使用了桥接模式之后,我们的两个维度就像桥梁一样被链接了起来。体现了松耦合的特性。

### 桥接模式的优点

1. 分离抽象和实现部分:把手机、内存抽象出来。实现与之分离。
2. 松耦合:两个维度分开
3. 单一职责原则:每个维度各干各的活

关于桥接模式的使用场景我觉得你只需要知道他的思想,然后在遇到问题的时候能够想到这种模式即可。