Design pattern - adapter pattern

Structural design mode

Structural pattern describes how to combine classes or objects to form a larger structure, just like building blocks, which can form a complex and more powerful structure through the combination of simple blocks.

Structural mode can be divided into class structural mode and object structural mode

The class structure pattern concerns about the combination of classes, which can be combined into a larger system. Generally, there are only inheritance and implementation relationships in the class structure pattern.

The object structure pattern concerns about the combination of class and object. It defines the instance object of another class in one class through association, and then calls its method through the object. According to the principle of composite reuse, we try to use association relationship instead of inheritance relationship in the system, so most structural patterns are object structural patterns.

concept

GOF defines the Adapter pattern as follows: transforming the interface of a class into another interface required by the user. The Adapter pattern enables classes that would otherwise not work together due to incompatible interfaces to work together. (analog travel socket converter)

Therefore, when an interface does not meet the current substitution rules, we can consider using adapter pattern and adding an adapter class to be compatible with interface calls.

Adapter pattern structure

The adapter pattern includes the following roles:

Target: target abstract class

Adapter: adapter class

Adapter: adapter class

Client: customer class

As shown in the figure, the Client cannot directly access the Adapter. An Adapter is an Adapter that converts an Adapter into an interface that the Client can access. Therefore, through the Adapter, the Client can access the Adapter. Target is the interface class provided.

PS: compared with the Adapter system, Target is the interface provided by adapterx.routerx.servicex, Adapter is the various SQL transformations configured, and Adaptee is the various called systems.

Code example

The following uses specific code to experience the specific writing method of adapter mode. Here's the list of mobile phone charging. We define an adapter. The function of the adapter is to use Android charger to charge Apple devices.

Define the interface first:

/**
 * MicroUsb Charger interface
 */
public interface MicroUsbInterface {
    public void chargeWithMicroUsb();
}

/**
 * Lightning Charger interface
 */
public interface LightningInterface {
    public void chargeWithLightning();
}

Define specific implementation classes

/**
 * Android device charger
 */
public class AndroidCharger implements MicroUsbInterface {
    @Override
    public void chargeWithMicroUsb() {
        System.out.println("Use MicroUsb Model charger charging...");
    }
}

/**
 * Chargers for Apple Devices
 */
public class AppleCharger implements LightningInterface {
    @Override
    public void chargeWithLightning() {
        System.out.println("Use Lightning Model charger charging...");
    }
}

Because we want to use adapter mode to convert MicroUsb to Lightning, the AppleCharger here does not need to be defined originally. Because the purpose of using the adapter is to replace the new one. This is defined to make the example more complete.

Define two phones

public class Iphone6Plus {

    private LightningInterface lightningInterface;

    public Iphone6Plus() {
    }

    public Iphone6Plus(LightningInterface lightningInterface) {
        this.lightningInterface = lightningInterface;
    }

    public void charge() {
        System.out.println("Start giving it to me Iphone6Plus Mobile charge...");
        lightningInterface.chargeWithLightning();
        System.out.println("It's over for me Iphone6Plus Mobile charge...");
    }

    public LightningInterface getLightningInterface() {
        return lightningInterface;
    }

    public void setLightningInterface(LightningInterface lightningInterface) {
        this.lightningInterface = lightningInterface;
    }
}

public class GalaxyS7 {

    private MicroUsbInterface microUsbInterface;

    public GalaxyS7() {
    }

    public GalaxyS7(MicroUsbInterface microUsbInterface) {
        this.microUsbInterface = microUsbInterface;
    }

    public void charge(){
        System.out.println("Start giving it to me GalaxyS7 Mobile charge...");
        microUsbInterface.chargeWithMicroUsb();
        System.out.println("Start giving it to me GalaxyS7 Mobile charge...");
    }

    public MicroUsbInterface getMicroUsbInterface() {
        return microUsbInterface;
    }

    public void setMicroUsbInterface(MicroUsbInterface microUsbInterface) {
        this.microUsbInterface = microUsbInterface;
    }
}

The purpose of defining a mobile phone here is to understand the adapter mode more easily, in which it plays no role.

Define adapter

/**
 * Adapter, converting MicroUsb interface to Lightning interface
 */
public class Adapter implements LightningInterface {
    private MicroUsbInterface microUsbInterface;

    public Adapter() {
    }

    public Adapter(MicroUsbInterface microUsbInterface) {
        this.microUsbInterface = microUsbInterface;
    }

    @Override
    public void chargeWithLightning() {
        microUsbInterface.chargeWithMicroUsb();
    }

    public MicroUsbInterface getMicroUsbInterface() {
        return microUsbInterface;
    }

    public void setMicroUsbInterface(MicroUsbInterface microUsbInterface) {
        this.microUsbInterface = microUsbInterface;
    }
}

The function of the adapter is to convert a microusb to Lightning. The implementation method is to implement the LightningInterface of the target class, and then use the combined method to define the microusb in the adapter. Then in the rewritten chargeWithLightning () method, microusb method is used to implement the specific details.

Defining clients

public class Main {

    public static void main(String[] args) {
        Iphone6Plus iphone6Plus = new Iphone6Plus(new AppleCharger());
        iphone6Plus.charge();

        System.out.println("==============================");

        GalaxyS7 galaxyS7 = new GalaxyS7(new AndroidCharger());
        galaxyS7.charge();

        System.out.println("==============================");

        Adapter adapter  = new Adapter(new AndroidCharger());
        Iphone6Plus newIphone = new Iphone6Plus();
        newIphone.setLightningInterface(adapter);
        newIphone.charge();
    }
}

Output results:

Start charging my iPhone 6plus
 Charging with a Lightning charger
 End charging my iPhone 6plus
==============================
Start charging my Galaxy S7 phone
 Charging with a micro USB charger
 Start charging my Galaxy S7 phone
==============================
Start charging my iPhone 6plus
 Charging with a micro USB charger
 End charging my iPhone 6plus

The above example uses a micro USB charger to charge the Iphone through an adapter. At the code level, the MicroUsb interface and its implementation classes are reused through the adapter. To a large extent, Fuyong has the existing code.

Concrete realization

  • InputStreamReader
  • OutputStreamWriter

Advantages and disadvantages

Advantage

Decouple the target class and the adapter class, and reuse the existing adapter class by introducing an adapter class without modifying the original code.

It increases the transparency and reusability of the class, encapsulates the specific implementation in the adapter class, which is transparent for the client class and improves the reusability of the adapter.

The flexibility and expansibility are very good. By using the configuration file, you can easily change the adapter, or add a new adapter class without modifying the original code, which fully conforms to the "open close principle".

shortcoming

Excessive use of adapters will make the system very messy and difficult to grasp as A whole. For example, it is obvious that the A interface is called, but in fact, it is internally adapted to the B interface implementation. If there are too many such cases in A system, it is no different from A disaster. So if it's not necessary, you can refactor the system directly instead of using the adapter.

For a class adapter, since JAVA inherits at most one class, at most one adapter class can be adapted, and the target class must be an abstract class

summary

Structural patterns describe how classes or objects can be combined to form larger structures.

The adapter pattern is used to transform one interface into another that the customer wants. The adapter pattern enables those classes that are not compatible with the interface to work together, and its alias is wrapper. The adapter pattern can be used as either a class structural pattern or an object structural pattern.

The adapter pattern consists of four roles:

The target abstract class defines the domain specific interface to be used by the customer;

The adapter class can call another interface, as a converter, to adapt the adapter and the abstract target class. It is the core of the adapter pattern;

The adapter class is the role to be adapted. It defines an existing interface, which needs to be adapted;

Program the target abstract class in the customer class, and call the business methods defined in the target abstract class.

In the object adapter mode, the adapter class inherits the object abstract class (or implements the interface) and defines an object instance of the adapter class, calling the corresponding business method of the adapter class in the inherited target abstract class method.

The main advantage of adapter pattern is to decouple the target class and the adapter class, increase the transparency and reusability of the class, at the same time, the flexibility and scalability of the system are very good, and it is very convenient to replace the adapter or add a new adapter, which conforms to the“ Opening and closing principle ”The disadvantage of class adapter pattern is that adapter classes can not adapt to multiple adapter classes at the same time in many programming languages, and the disadvantage of object adapter pattern is that it is difficult to replace the method of adapter classes.

The application of adapter pattern includes: the system needs to use existing classes, and the interfaces of these classes do not meet the needs of the system; and the system wants to establish a reusable class for working with some classes that are not very related to each other.

Reference material

Tags: Java Mobile Android socket SQL

Posted on Mon, 16 Mar 2020 03:30:38 -0400 by timmah22