Adapter mode of java design mode (Adapter)

concept

GOF defines the adapter pattern ( Adapter) in this way: convert the interface of a class into another interface that the user needs. The Adapter pattern enables classes that would otherwise not work together due to incompatible interfaces to work together.

In GOF, the adapter pattern is divided into class adapter pattern and object adapter pattern. The only difference is whether the adaptation of the adapter role to the adapted role is realized through inheritance or combination. Because multiple inheritance is not supported in Java, and it is suspected of breaking encapsulation. And we also advocate [multiple combinations and less inheritance][2]. So this article mainly introduces the object adapter.

use

I believe everyone has this common sense of life: the models of electronic device chargers we use are different. The current mainstream mobile phone charger ports mainly include Mini Usb, Micro Usb and Lightning. Among them, Mini Usb widely appears in card readers, MP3, digital cameras and mobile hard disks. Because Micro Usb is thinner than Mini Usb, it is widely used in mobile phones, common in Android phones. Another common charger port is Lightning, which is commonly used in Apple mobile phones.

Of course, certain models of phones can only be charged with certain models of chargers. For example, the iPhone 6 can only be charged with a charger with a Lightning interface. However, if we only have an Android Micro Usb charger cable around us, can we charge Apple phones? The answer is yes, as long as there is an adapter.

adapter

Adapters can be seen everywhere in our daily life. Adapter pattern is exactly to solve a similar problem.

We may also encounter similar scenarios during the program design process:

1. The system needs to use existing classes, and such interfaces do not meet the needs of the system.

2. I want to create a reusable class for working with some classes that are not very related to each other, including some classes that may be introduced in the future. These source classes do not necessarily have a consistent interface.

3. Insert a class into another class system through interface conversion. (For example, tigers and birds, now there is a flying tiger. Without increasing the requirements of the entity, add an adapter, which contains a tiger object, and realizes the interface of flying.)

The above scenarios are suitable for using the adapter pattern.

Method to realize

The adapter pattern includes the following roles:

Target: target abstract class

Adapter: adapter class

Adaptee: Adapter class

Client: client class

Adapter-pattern

Here we use the example of the mobile phone charging port introduced at the beginning of the article. We define an adapter whose function is to use the Android charger to charge the Apple device.

First define the interface:

/**
 * MicroUsb充电器接口
 */
public interface MicroUsbInterface {
    public void chargeWithMicroUsb();
}

/**
 * Lightning充电器接口
 */
public interface LightningInterface {
    public void chargeWithLightning();
}

Define a concrete implementation class

/**
 * 安卓设备的充电器
 */
public class AndroidCharger implements MicroUsbInterface {
    @Override
    public void chargeWithMicroUsb() {
        System.out.println("使用MicroUsb型号的充电器充电...");
    }
}

/**
 * 苹果设备的充电器
 */
public class AppleCharger implements LightningInterface {
    @Override
    public void chargeWithLightning() {
        System.out.println("使用Lightning型号的充电器充电...");
    }
}

Because we want to use the adapter mode to convert MicroUsb to Lightning, the AppleCharger here does not need to be defined. Because our purpose of using the adapter is to replace a new one. It is defined here 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("开始给我的Iphone6Plus手机充电...");
        lightningInterface.chargeWithLightning();
        System.out.println("结束给我的Iphone6Plus手机充电...");
    }

    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("开始给我的GalaxyS7手机充电...");
        microUsbInterface.chargeWithMicroUsb();
        System.out.println("结束给我的GalaxyS7手机充电...");
    }

    public MicroUsbInterface getMicroUsbInterface() {
        return microUsbInterface;
    }

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

The role of the mobile phone is defined here for a more convenient understanding of the adapter mode, in which he does not play any role.

Define the adapter

/**
 * 适配器,将MicroUsb接口转成Lightning接口
 */
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 this adapter is to convert a MicroUsb into Lightning. The implementation method is to implement the interface ( LightningInterface) of the target class, and then use the combined method to define microUsb in the adapter. Then in the rewritten chargeWithLightning()method, use the method of microUsb to realize the specific details.

define client

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 result:

开始给我的Iphone6Plus手机充电...
使用Lightning型号的充电器充电...
结束给我的Iphone6Plus手机充电...
==============================
开始给我的GalaxyS7手机充电...
使用MicroUsb型号的充电器充电...
结束给我的GalaxyS7手机充电...
==============================
开始给我的Iphone6Plus手机充电...
使用MicroUsb型号的充电器充电...
结束给我的Iphone6Plus手机充电...

The above example uses a MicroUsb type charger to charge an Iphone through an adapter. From the code level, the MicroUsb interface and its implementation class are reused through the adapter. Existing code is largely reused.

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.

The transparency and reusability of the class are increased, and the specific implementation is encapsulated in the adapter class, which is transparent to the client class and improves the reusability of the adapter.

The flexibility and scalability are very good. By using the configuration file, the adapter can be easily replaced, and a new adapter class can be added without modifying the original code, which fully complies with the "open and 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 the internal implementation is actually adapted to the implementation of the B interface. If this happens too much in a system, it is tantamount to a disaster. Therefore, if it is not necessary, you can directly refactor the system without using the adapter.

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

Summarize

Structural patterns describe how classes or objects are grouped together to form larger structures.

The adapter pattern is used to convert an interface into another interface that the client wants. The adapter pattern enables those classes with incompatible interfaces to work together, and its alias is a wrapper. The Adapter pattern can be used both as a class-structural pattern and as 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 client;

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

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

Program the target abstract class in the client class, and call the business method defined in the target abstract class.

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

The main advantage of the adapter mode is to decouple the target class and the adapter class, which increases the transparency and reusability of the class. At the same time, the flexibility and scalability of the system are very good. It is very convenient to replace the adapter or add a new adapter. , in line with "[opening and closing principle][3]"; the disadvantage of the class adapter pattern is that the adapter class cannot adapt to multiple adapter classes at the same time in many programming languages, and the disadvantage of the object adapter pattern is that it is difficult to replace the adapter class Methods.

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

Guess you like

Origin blog.csdn.net/zy_dreamer/article/details/132364268