Skip to content

Commit

Permalink
update: refactory adapter
Browse files Browse the repository at this point in the history
  • Loading branch information
hscspring committed Oct 22, 2022
1 parent 5c00af5 commit 0dd039e
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 22 deletions.
181 changes: 160 additions & 21 deletions docs/content/design_pattern/adapter.md
Original file line number Diff line number Diff line change
@@ -1,56 +1,195 @@
# 适配器模式

## 设计动机
## 模式引入

**问题引入**
### 问题描述

想象我们要出国旅游,到了异国他乡不懂当地语言怎么办?路上卯足马力突击学习?当然可以!不过更简单的做法是,打开手机翻译软件,切换到「当地语言-中文」就可以借助它与当地人进行对话了。这样,只要我们手机里有其他语言与中文的互译,就可以走遍地球任意一个角落并和当地人沟通了,而且我们自己并不需要真正掌握任何一门外语。

**模式引入**
当然,有时候用翻译软件有点麻烦,有不准确的情况。此时,可以在当地找一个翻译,比如领导人出访国外时会带一个翻译,刚去 NBA 打球的姚明也随时有一个翻译在身边。

### 模式定义

这就是适配器模式,它一般在有满足需求功能的类,但接口不符合要求,或者希望创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作时出现。总的来说,它的主要目的是希望能复用已有的类,但接口又与复用环境要求不一致。

上面的例子中,中文与其他语言的互译器就是一个个适配器,我们自己就是那个已有的满足功能的类,接口和环境就是异国他乡。
适配器模式是将一个类的接口转换成客户希望的另外一个接口。使得原来接口不兼容的类可以一起工作。

### 问题分析

上面的例子中,中文与其他语言的互译器以及翻译人员就是适配器,我们自己或姚明就是那个已有的满足功能的类,接口和环境就是异国他乡。

## 模式介绍

**模式定义**
### 解决方案

适配器模式是将一个类的接口转换成客户希望的另外一个接口。使得原来接口不兼容的类可以一起工作。
- 定义 `Target` 抽象类:`Player`,以及方法 `attact``defense`
- 实现 `ConcreteTarget` 具体类:`Forwards``Center``Guards` 等,并重写抽象方法。
- 定义 `Adaptee``ForeignCenter`,他的方法和抽象类的不一样,需要适配。
- 使用 `Adapter``Translator` 将需要适配的 `Adaptee``ForeignCenter` 转换为 `Target`

**实现方式**
下面是一些注意事项:

- 一般在开发后期或维护期,双方都比较稳定、不太容易修改时候才会使用。

**模式结构**
### 代码实现

`Target` 抽象类:

```java
public abstract class Player {
protected String name;
public Player(String name) {
this.name = name;
}

public abstract void attack();
public abstract void defense();
}
```

`Target` 具体类:

```java
public class Forwards extends Player {
public Forwards(String name) {
super(name);
}

@Override
public void attack() {
System.out.println("前锋 " + name + " 进攻");
}

@Override
public void defense() {
System.out.println("前锋 " + name + " 防守");
}
}

public class Center extends Player {
public Center(String name) {
super(name);
}

@Override
public void attack() {
System.out.println("中锋 " + name + " 进攻");
}

@Override
public void defense() {
System.out.println("中锋 " + name + " 防守");
}
}

public class Guards extends Player {
public Guards(String name) {
super(name);
}

@Override
public void attack() {
System.out.println("后卫 " + name + " 进攻");
}

@Override
public void defense() {
System.out.println("后卫 " + name + " 防守");
}
}
```

`Adaptee` 类:

```java
public class ForeignCenter {
private String name;
public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public void attack() {
System.out.println("外籍中锋 " + name + " 进攻");
}

public void defense() {
System.out.println("外籍中锋 " + name + " 防守");
}
}
```

`Adapter` 类:

```java
public class Translator extends Player {
private ForeignCenter wjzf = new ForeignCenter();

public Translator(String name) {
super(name);
wjzf.setName(name);
}

@Override
public void attack() {
wjzf.attack();
}

@Override
public void defense() {
wjzf.defense();
}
}
```

`Main` 方法:

```java
public class Main {
public static void main(String[] args) {
Player b = new Forwards("巴蒂尔");
b.attack();

Player m = new Guards("麦克格雷迪");
m.attack();

Player ym = new Translator("姚明");
ym.attack();
ym.defense();
}
}
```

### 结构组成

![](img/adapter/adapter.jpeg)

**代码实现**

- C++ 实现:[链接](https://github.com/datawhalechina/sweetalk-design-pattern/tree/main/src/design_patterns/cpp/adapter)
- Java 实现:[链接](https://github.com/datawhalechina/sweetalk-design-pattern/tree/main/src/design_patterns/java/adapter)
- Python 实现:[链接](https://github.com/datawhalechina/sweetalk-design-pattern/tree/main/src/design_patterns/python/adapter)
- Target:客户所期待的接口,可以是具体类、抽象类或接口。
- Adaptee:需要适配的类。
- Adapter:通过在内部包装一个 Adaptee 对象,把源接口转换为目标接口。

## 使用场景
## 模式评价

**适合场景**
### 适用场景

- 系统数据和行为正确,但接口不符时。
- 系统数据和行为正确,但接口不符时。比如上面姚明他听不懂英文的进攻和防守。
- 扩展新功能接入第三方接口时。

**实际应用**
### 实际应用

实际中的例子:复用功能但接口不符,俗称包一层。

## 模式评价
### 优点缺点

**模式优点**
适配模式优点包括:

- 接口与业务逻辑解耦。
- 接口与业务逻辑解耦。Adapter 只要和 Target 对齐就行,Client 根本不关心 Adaptee 具体怎么和 Adapter 对接,它甚至不需要知道 Adaptee 的存在。
- 容易扩展。

**不足之处**
适配模式缺点包括:

- 代码复杂度增加。

6 changes: 5 additions & 1 deletion docs/content/design_pattern/state.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

- 抽象状态 `State`,定义一个抽象方法,如 `writeProgram`
- 实现不同的具体状态 `Concrete` 类:`ForenoonState``NoonState``AfternoonState`等,并重写抽象方法。
- 实现一个上下文类:`Work` 用来管理状态的变化
- 实现一个上下文类:`Work` 用来管理当前状态

下面是一些注意事项:

Expand Down Expand Up @@ -194,6 +194,10 @@ public class Main {

![](img/state/state.jpeg)

- State:抽象状态类,定义一个接口用来封装与 Context 的一个特定状态相关的行为。
- ConcreteState 类:具体状态类,每个子类实现一个与 Context 一个状态相关的行为。
- Context 类:维护一个 ConcreteState 子类的实例,定义当前状态。

## 模式评价

### 适用场景
Expand Down

0 comments on commit 0dd039e

Please sign in to comment.