Design Pattern | Adapter Pattern

1 | Overview of Adapter Mode

Let’s think of a common life phenomenon. Our country’s life electricity voltage is 220V, but the actual working voltage of mobile phones, notebooks, TVs and other equipment is not so high. In order for these equipment to use 220V life electricity, it is necessary The power adapter (AC Adpater) is also a charger or a transformer. With this power adapter, household appliances and other equipment that cannot work directly can be used compatible, and the power adapter among them acts as an adapter.

Similarly in software development, this kind of similar incompatibility sometimes occurs. We can also introduce a role called an adapter like a power adapter to coordinate these incompatible structures. This This design scheme is the adapter mode. 

Similar to the power adapter, a packaging class called Adapter is introduced in the adapter mode, and the object it wraps is called Adaptee, which is the class to be adapted. The realization of the adapter is to convert the request of the client class into a call to the corresponding interface of the adapter. That is to say: when the client class calls the method of the adapter, the method of the adapter class will be called inside the adapter class, and this process is transparent to the client class, and the client class does not directly access the adapter class. Therefore, the adapter allows classes that cannot interact due to incompatible interfaces to work together.

1.1 Definition of Adapter Mode

  • Adapter pattern : Convert the interface of a class into another interface that the customer wants. The adapter mode allows classes with incompatible interfaces to work together.
  • Adapter Pattern: Convert the interface of a class into another interface clients expect. Adapter lets casses work together that could't otherwise because of icompaible nteraces.

The adapter pattern can match the interface of one class with the interface of another class without modifying the original adapter interface and the abstract target interface class.

The alias of the adapter pattern is the wrapper pattern , which can be used as either a class structure pattern or an object structure pattern . The interface mentioned in the adapter pattern definition refers to a broad interface, which can represent a method or a collection of methods.

2 | The structure and implementation of the adapter pattern

The adapter pattern includes class adapter and object adapter. In the object adapter pattern, there is an association relationship between the adapter and the adapter; in the class adapter pattern, the adapter and the adapter have an inheritance (or realization) relationship. The following is a structural analysis of the two adapters.

2.1 The structure of the adapter mode

The adapter mode contains the following 3 roles

  • (1) Target (target abstract class): The target abstract class defines the interface required by the customer, which can be an abstract class or interface, or a concrete class. In the class adapter, due to the C# language feature single inheritance and multiple interface extensions.
  • (2) Adapter (Adapter class): It can call another interface as a converter to adapt Adaptee and Target. Adapter is the core of the adapter pattern. In the class adapter, it connects the two by implementing the Target interface and inheriting the Adaptee class. In the object adapter, it connects the two by inheriting Target and associating an Adaptee object.
  • (3) Adaptee (adapter class): The adaptor is the role to be adapted. It defines an existing interface that needs to be adapted. The adaptor class is generally a specific class, and the sentence contains the client The business method you want to use may not even have the source code of the adaptor class in some cases.

2.2 Implementation of Adapter Mode

Since the adapter mode includes two forms of class adapter mode and object adapter mode, the following describes the implementation mechanisms of these two adapter modes.

2.2.1 Class Adapter

In the class adapter, the adaptee class Adaptee does not have a Beavast() method, and the client expects this method, but the SpecificRequest() method is implemented in the adaptor class. The implementation provided by this method is exactly what the client needs. In order to enable customers to use the adaptor class, an intermediate class is provided, namely the Adaptet class. The adaptor class implements the object object class interface Target and inherits the adaptor class. In the Reqpest() of the adaptor class The method calls the SpecificRequest() method of the inherited adapter class to achieve the purpose of adaptation. Because the adapter class and the adapter class are inherited , this adapter mode is called the class adapter mode. The typical class adapter code is as follows:

interface ITarget
{
    string Request();
}

class Adaptee
{
    public string SpecificRequest() => "Adaptee.SpecificRequest";
}

class ClassAdapter : Adaptee, ITarget
{
    public string Request() => $"ClassAdapter.Request 调用 {base.SpecificRequest()}";
}

2.2.2 Object adapter

In the object adapter, the client needs to call the Request() method, while the Adaptee class does not have this method but the SpecificRequest() method it provides is what the client needs. In order to enable the client to use the adapter class, it is necessary to provide a wrapper class Adapter, the adapter class. This wrapper class wraps an instance of an adaptor to connect the client with the adaptor, and call the Adaptor's SpecificRequest() method in the adaptor's Request() method. Because the adapter class and the adapter class are in an association relationship (also called a delegation relationship ), this adapter pattern is called an object adapter pattern. The typical object adapter code is as follows:

class ObjectAdapter : ITarget
{
    private readonly Adaptee _Adaptee; //维持一个适配者对象的引用

    public ObjectAdapter(Adaptee adaptee)
    {
        _Adaptee = adaptee;
    }

    public string Request() => $"ObjectAdapter.Request 调用 {_Adaptee.SpecificRequest()}";
}

The adapter pattern can match the interface of one class with the interface of another class. The premise of using it is that you cannot or do not want to modify the original adapter interface and the abstract target class interface. For example: Some third-party class libraries or controls are purchased, but there is no source code. At this time, the adapter mode can be used to unify the object access interface.
The adapter pattern emphasizes more on the organization of the code, rather than the realization of the function. In actual development, the frequency of use of object adapters is higher.

Client call

3 | Application examples of the adapter pattern

Code design

  1. ScoreOperation: An abstract score operation class that serves as a target interface.
  2. QuickSortClass: Quick sort class, acting as an adaptor.
  3. BinarySearchClass: Binary search class, acting as an adaptation class.
  4. The configuration file App.config stores the class name (full name) of the adapter class in the configuration file.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="adapter" value="AdapterPattern.Sample.OperationAdapter"/>
  </appSettings>
</configuration>

For the details of the above code, please check=》https://gitee.com/dolayout/DesignPatternOfCSharp/tree/master/DesignPatternOfCSharp/AdapterPattern

Client call

4 | Default adapter mode

The default adapter mode is a variant of the adapter mode, and its application is also more widespread. This mode is also called the single-interface adapter mode .

4.1 Definition of default adapter mode

  • Default Adapter Pattern : When you do not need to implement all the methods provided by an interface, you can first design an abstract class to implement the interface, and provide a default implementation (empty method) for each method in the interface, Then the subclass of this abstract class can selectively override some methods of the parent class to achieve the requirements. It is suitable for situations where you do not want to use all the methods in an interface, which is also called the single-interface adapter mode.

4.2 The default adapter mode contains the following 3 roles:

  • (1) IServiceInterface (adapter interface) : It is an interface, and usually a large number of methods are declared in the interface.
  • (2) AbstractServiceClass (default adapter class) : It is the core class of the default adapter pattern, which implements the methods declared in the ServiceInterface interface in the form of empty methods. It is usually defined as an abstract class, because it does not make any sense to instantiate it.
  • (3) ConcreteServiceClass (specific service class) : It is a subclass of the default adapter class. Before the adapter is introduced, it needs to implement the adapter interface, so it needs to implement all the methods declared in the adapter interface. Some methods that do not need to be used have to provide empty implementations. After having the default adapter, you can directly inherit the adapter class and selectively override the methods defined in the adapter class as needed.

Among them, the typical code snippet of the default adapter class is as follows:

interface IServiceInterface 
{
    void ServiceMethod1();
    void ServiceMethod2();
    void ServiceMethod3();
}

abstract class AbstractServiceClass : IServiceInterface
{
    public void ServiceMethod1() { } // 空方法
    public void ServiceMethod2() { }
    public void ServiceMethod3() { }
}

5 | Two-way adapter mode

During the use of the object adapter, if the adapter contains references to both the target class and the adapter class, the adapter can use it to call methods in the target class, and the target class can also call the adapter class through it. Method, then the adapter is a two-way adapter.

The implementation of the two-way adapter is more complicated, and its typical code is as follows:

class TwoWayApapter : Adaptee, ITarget
{
    // 同时维持抽象目标类和适配者的引用
    private readonly Adaptee _Adaptee;
    private readonly ITarget _Target;

    public TwoWayApapter(Adaptee adaptee) 
    {
        _Adaptee = adaptee;
    }

    public TwoWayApapter(ITarget target)
    {
        _Target = target;
    }

    public new string SpecificRequest() => _Target.Request();

    public string Request() => _Adaptee.SpecificRequest();

}

6 | Advantages and disadvantages of adapter mode and applicable environment

The adapter pattern transforms the existing interface into the interface expected by the customer class, and realizes the reuse of the existing class. It is a design pattern with a very high frequency of use and has been widely used in software development.

6.1 Advantages of the adapter mode (both the object adapter mode and the class adapter mode)

  • (1) Decouple the target class and the adaptor class, and reuse the existing adaptor class by introducing an adaptor class without modifying the original structure.
  • (2) Increase the transparency and reusability of the class, encapsulate the specific business realization process in the adaptor class, which is transparent to the client class, and improves the reusability of the adaptor. One is that the adapter class can be reused in multiple different systems.
  • (3) Flexibility and scalability are very good. Through the use of configuration files, the adapter can be easily replaced, and new adapter classes can be added without modifying the original code, which is fully in line with the opening and closing principles.

Specifically, the class adapter pattern also has the following advantages:

  • Since the adapter class is a subclass of the adapter class, some adaptor methods can be replaced in the adapter class to make the adapter more flexible.

Object adapter mode also has the following advantages:

  • (1) An object adapter can adapt multiple different adapters to the same target.
  • (2) The object adapter mode can adapt to a subclass of an adaptor. Since the adapter and the adaptor are associated, according to the Richter substitution principle, the subclass of the adaptor can also be adapted through the adaptor .

6.2 Disadvantages
of the adapter mode The main disadvantages of the class adapter mode are as follows:

  • (1) For languages ​​that do not support multiple class inheritance, such as C# and Java, at most one adaptor class can be adapted at a time, and multiple adaptors can be adapted at the same time.
  • (2) The adaptor class cannot be the final class, for example, it cannot be the sealed class in C#.
  • (3) In languages ​​such as C# and Java, the target abstract class in the class adapter pattern can only be an interface, not a class, and its use has certain limitations.

The main disadvantages of the object adapter pattern are as follows:

  • Compared with the class adapter pattern, some methods of replacing the adapter class in the adapter are more troublesome. If you must replace one or more methods of the adaptor class, you can first make a subclass of the adaptor class, remove the method of the adaptor class, and then treat the subclass of the adaptor class as the real The adaptation process of the adaptor is more complicated.

6.3 Applicable environment of adapter mode

  • (1) The system needs to use some existing classes, and the interfaces of these classes (such as method names) do not meet the needs of the system, and there is even no source code for these classes.
  • (2) Create a reusable class to work with classes that are not very related to each other, including classes that may be introduced in the future.

 

Guess you like

Origin blog.csdn.net/ChaITSimpleLove/article/details/115056329