Python 设计模式:适配器模式

适配器模式是一种 结构型设计模式, 它能使接口不兼容的对象能够相互合作。通过 组合对象的方式来创建新功能。

什么是适配器

适配器帮助我们使两个不兼容的接口兼容。这到底是什么意思呢?如果我们有一个旧的组件,我们想在一个新的系统中使用它,或者我们想在一个旧的系统中使用一个新的组件。两者很少能在不需要修改代码的情况下进行交流。

然而,更改代码并不总是可能的,要么因为我们无法访问它,要么因为它不切实际。在这种情况下,我们可以编写一个附加层,对两个接口之间的通信进行必要的修改,实现两个接口之间的通信。

[En]

However, it is not always possible to change the code, either because we cannot access it or because it is impractical. In this case, we can write an additional layer, make some necessary modifications to the communication between the two interfaces, and implement the communication between the two interfaces.

这个层被称为适配器。

适配器的作用

适配器不仅可以转换不同格式的数据,还可以促进具有不同接口的对象之间的协作。它的工作原理如下:

[En]

Adapters can not only convert data in different formats, but also facilitate cooperation between objects with different interfaces. It works as follows:

  1. 适配器实现与其中一个现有对象兼容的接口。
  2. 现有对象可以使用该接口安全地调用适配器方法。
  3. 适配器方法被调用后将以另一个对象兼容的格式和顺序将请求传递给该对象。

有时,您甚至可以创建双向适配器来实现双向转换调用。

[En]

Sometimes you can even create a two-way adapter to implement two-way transformation calls.

真实世界的例子

  1. 不同国家的电源插头和插座标准不同。 美国插头和德国插座不匹配。 同时提供美国标准插座和欧洲标准插头的电源适配器可以解决你的难题。当你从大多数欧洲国家到英国或美国旅行,你需要使用电源适配器为你的笔记本电脑充电。
  2. 不同的电子产品的适配接口也不一样,比如相机和手机的接口不同。当你使用不同的电子产品,需要不同读取数据的接口:USB、HDMI、VGA 等接口。

适配器模式结构

对象适配器

当我们的 client 想要打开风扇,而风扇提供了 ​ ​turnOn​​ 方法,直接调用 ​ ​turnOn​​ 即可享受凉爽的风,比如下图:

Python 设计模式:适配器模式

然后同样是打开的操作,client 想通过 ​ ​turnOn​​ 调用打开电视机,而电视机没有这个方法,电视机提供的 ​ ​open​​ 方法。

Python 设计模式:适配器模式

如果我们直接把 ​ ​open​​ 方法改为 ​ ​turnOn​​ 的方法,可能会引发系统的一系列其他问题,这个时候就需要我们的适配器模式了。

客户端可以会使用各种各样的适配器,为了方便保存,可以为适配器抽象出一个接口,UML 图如下:

Python 设计模式:适配器模式

适配器 (Adapter) 是一个可以同时与客户端和服务交互的类: 它在实现客户端接口的同时封装了服务对象。 适配器接受客户端通过适配器接口发起的调用, 并将其转换为适用于被封装服务对象的调用。

客户端代码只需要通过接口与适配器交互,而不需要与特定的适配器类耦合。因此,您可以在不修改现有代码的情况下向程序添加新类型的适配器。当更改或替换服务类的接口时,这很有用:您可以在不修改客户端代码的情况下创建新的适配器类。

[En]

The client code only needs to interact with the adapter through the interface and does not need to be coupled with the specific adapter class. Therefore, you can add new types of adapters to the program without modifying existing code. This is useful when the interface of a service class is changed or replaced: you can create a new adapter class without modifying the client code.

代码如下:

public interface IAdapter {  public void turnOn(); // 通用开机函数}public class Tv {  public void open() {    System.out.println("电视机 TV 开机,只能使用 open 函数");  }}public class TvAdapter extends Tv implements IAdapter {  public void turnOn() {    super.open(); // 适配器模式  }}

调用方式:

public class Main {  public static void main(String[] args) {    IAdapter adapter = new TvAdapter();    adapter.turnOn();  }}

类适配器

这一实现使用了继承机制: 适配器同时继承两个对象的接口。 请注意, 这种方式仅能在支持多重继承的编程语言中实现, 例如 C++。

Python 设计模式:适配器模式

Python 实现

class Target:    """    The Target defines the domain-specific interface used by the client code.    """    def request(self) -> str:        return "Target: The default target's behavior."class Adaptee:    """    The Adaptee contains some useful behavior, but its interface is incompatible    with the existing client code. The Adaptee needs some adaptation before the    client code can use it.    """    def specific_request(self) -> str:        return ".eetpadA eht fo roivaheb laicepS"class Adapter(Target, Adaptee):    """    The Adapter makes the Adaptee's interface compatible with the Target's    interface via multiple inheritance.    """    def request(self) -> str:        return f"Adapter: (TRANSLATED) {self.specific_request()[::-1]}"def client_code(target: "Target") -> None:    """    The client code supports all classes that follow the Target interface.    """    print(target.request(), end="")if __name__ == "__main__":    print("Client: I can work just fine with the Target objects:")    target = Target()    client_code(target)    print("\n")    adaptee = Adaptee()    print("Client: The Adaptee class has a weird interface. "          "See, I don't understand it:")    print(f"Adaptee: {adaptee.specific_request()}", end="\n\n")    print("Client: But I can work with it via the Adapter:")    adapter = Adapter()    client_code(adapter)

运行该程序:

Client: I can work just fine with the Target objects:Target: The default target's behavior.Client: The Adaptee class has a weird interface. See, I don't understand it:Adaptee: .eetpadA eht fo roivaheb laicepSClient: But I can work with it via the Adapter:Adapter: (TRANSLATED) Special behavior of the Adaptee.

适配器模式优缺点

优点:

  • 单一责任原则可以将接口或数据转换代码从程序的主要业务逻辑中分离出来。
    [En]

    single responsibility principle you can separate the interface or data conversion code from the main business logic of the program.*

  • 开闭原则。 只要客户端代码通过客户端接口与适配器进行交互, 你就能在不修改现有客户端代码的情况下在程序中添加新类型的适配器。

缺点:

  • 代码整体复杂度增加, 因为你需要新增一系列接口和类。 有时直接更改服务类使其与其他代码兼容会更简单。

参考链接:

Original: https://blog.51cto.com/yuzhou1su/5412347
Author: 宇宙之一粟
Title: Python 设计模式:适配器模式

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/513876/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球