Python design pattern: Adapter Pattern

InfoQ 2022-06-23 19:31:57 阅读数:332


Adapter pattern
It's a kind of
Structural type
Design patterns ,  It enables objects with incompatible interfaces to cooperate with each other . adopt
Object to create new functions .

What is an adapter

Help us make two incompatible interfaces compatible . What exactly does this mean ? If we have an old component , We want to use it in a new system , Or we want to use a new component in an old system . The two rarely communicate without modifying the code .

however , Changing the code is not always possible , Or because we can't access it , Or because it's unrealistic . under these circumstances , We can write an extra layer , Make some necessary modifications to the communication between the two interfaces , Communication between two interfaces .

This layer is called an adapter .

Function of adapter

The adapter can not only convert data in different formats ,  It also facilitates cooperation between objects that use different interfaces .  It works as follows :
  • The adapter implements an interface compatible with one of the existing objects .
  • Existing objects can use this interface to safely call adapter methods .
  • When the adapter method is called, the request is passed to another object in a format and order that is compatible with that object .

Sometimes you can even create a bidirectional adapter to implement bidirectional conversion calls .

Real world examples

  • Different countries have different standards for power plugs and sockets .  The American plug does not match the German socket .  At the same time, the power adapter with American standard socket and European standard plug can solve your problem . When you travel from most European countries to Britain or the United States , You need to use a power adapter to charge your laptop .
  • Different electronic products have different interfaces , For example, the interface between camera and mobile phone is different . When you use different electronic products , Different interfaces for reading data are required :USB、HDMI、VGA  Such as the interface .

Adapter pattern structure

Object adapter
When our  client  Want to turn on the fan , And the fan provides  
  Method , Call directly  
  Enjoy the cool wind , For example, below :
Then it is the same open operation ,client  Want to pass  
  Call to turn on the TV , Television doesn't have this method , TV sets provide  
  Method .
If we just  
  Methods to  
  Methods , It may cause a series of other problems in the system , At this time, we need our adapter mode .

Clients can use a variety of adapters , For convenience of storage , You can abstract out an interface for the adapter ,UML  The graph is as follows :

 (Adapter)  Is a class that can interact with clients and services at the same time :  It encapsulates the service object while implementing the client interface .  The adapter accepts calls from the client through the adapter interface ,  And turn it into a call for the encapsulated service object .

The client code only needs to interact with the adapter through the interface ,  No need to couple with specific adapter classes .  therefore ,  You can add new types of adapters to the program without modifying the existing code .  This is useful when the interface of the service class is changed or replaced :  You can create a new adapter class without modifying the client code .

The code is as follows :
public interface IAdapter {
 public void turnOn(); //  General boot function

public class Tv {
 public void open() {
 System.out.println(" The TV  TV  Turn it on , Only use  open  function ");

public class TvAdapter extends Tv implements IAdapter {
 public void turnOn() {; //  Adapter pattern

Call mode :
public class Main {
 public static void main(String[] args) {
 IAdapter adapter = new TvAdapter();

The class adapter
This implementation uses an inheritance mechanism :  The adapter inherits the interface of both objects .  Please note that ,  This approach can only be implemented in programming languages that support multiple inheritance ,  for example  C++.

Python  Realization

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()

 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()

Run the program :
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 laicepS

Client: But I can work with it via the Adapter:
Adapter: (TRANSLATED) Special behavior of the Adaptee.

The advantages and disadvantages of adapter mode

advantage :
    Principle of single responsibility
    You can separate the interface or data conversion code from the main business logic of the program .
    Opening and closing principle
    .  As long as the client code interacts with the adapter through the client interface ,  You can add a new type of adapter to your program without modifying the existing client code .
shortcoming :
  •   The overall complexity of the code increases ,  Because you need to add a series of interfaces and classes .  Sometimes it's easier to change the service class directly to make it compatible with other code .

Reference link :
  • Adapter pattern
  • Cartoon object oriented programming :16.13  Adapter pattern : Proud electrical appliances