Basic introduction

  1. Adapter Pattern converts the interface of a class into another interface representation expected by the client. The main purpose is compatibility, so that two classes that cannot work together due to interface mismatch can work together. Its alias is Wrapper
  2. The adapter pattern is a structural pattern
  3. There are three main categories: class adapter pattern, object adapter pattern and interface adapter pattern

The working principle of

  1. Adapter pattern: Converts an interface from one class to another. Make classes compatible with incompatible interfaces
  2. From the user’s point of view, you can’t see the matched, it’s decoupled
  3. The user calls the target interface methods transformed by the adapter, and the adapter calls the corresponding interface methods of the adaptor

Type of adapter

Adapter-like pattern

Basic introduction

Adapter class, by inheriting SRC class, DST class interface, complete SRC -> DST adaptation.

Application Example

The charger itself is equivalent to Adapter. 220V AC is equivalent to SRC (the adaptor). Our aim DST (the target) is 5V direct current

The code analysis

package adapter.classAdapter; /** * @author Y2M * @createTime 2021/6/5 * @comment */ public class Phone {/** ** public void change (IVoltage5V IVoltage5V){if(iVoltage5v.output5v () == 5) {system.out.println (" voltage is 5V, can charge ~~"); if(ivoltage5v.output5v () == 5) {system.out.println (" voltage is 5V, can charge ~~"); } else if (iVoltage5V.output5v () > 5) {system.out.println (" voltage > 5V, can't charge ~~"); }}}Copy the code
package adapter.classAdapter; /** * @author Y2M * @createTime 2021/6/5 * @comment Public class Voltage220V {/** * outputs 220V */ public int output220V() { int src = 220; Println (" source voltage =" + SRC + v "); return src; }}Copy the code
package adapter.classAdapter; /** * @author Y2M * @createTime 2021/6/5 * @comment IVoltage5V */ public interface IVoltage5V {/** ** output 5V * @return */ public int output5V(); }Copy the code
package adapter.classAdapter; /** * @author Y2M * @createTime 2021/6/5 * @comment public class VoltageAdapter extends Voltage220 implements @override public int output5V() {int srcV = output5V(); Int dstV = srcV / 44; return dstV; }}Copy the code
package adapter.classAdapter; /** * @author Y2M * @createTime 2021/6/5 * @comment */ public class Client { public static void main(String[] args) { System.out.println(" === class adapter pattern ===="); Phone phone = new Phone(); phone.changing(new VoltageAdapter()); }}Copy the code

Class adapter pattern considerations and details

  1. Java is a single-inheritance mechanism, so the fact that the class adapter needs to inherit SRC classes is a disadvantage because it requires DST to be an interface, which has some limitations.
  2. SRC class methods are exposed in Adapter, which increases the cost of using them
  3. Because it inherits the SRC class, it can override the methods of the SRC class as needed, making the Adapter more flexible.

Object adapter pattern

introduce

  1. The basic idea is the same as the Adapter pattern of the class, except that the Adapter class is modified. Instead of inheriting the SRC class, the Adapter class holds an instance of the SRC class to resolve compatibility issues. That is: hold SRC class, implement DST class interface, complete SRC -> DST adaptation
  2. According to the principle of composite reuse, association relation is used to replace inheritance relation
  3. The object adapter pattern is one of the commonly used adapter patterns

The code analysis

package adapter.objectAdapter; /** * @author Y2M * @createTime 2021/6/5 * @comment */ public class Phone {/** ** public void change (IVoltage5V IVoltage5V){if(iVoltage5v.output5v () == 5) {system.out.println (" voltage is 5V, can charge ~~"); if(ivoltage5v.output5v () == 5) {system.out.println (" voltage is 5V, can charge ~~"); } else if (iVoltage5V.output5v () > 5) {system.out.println (" voltage > 5V, can't charge ~~"); }}}Copy the code
package adapter.objectAdapter; Public interface IVoltage5V {public int output5V(); /** * @author Y2M * @createTime 2021/6/5 * @comment }Copy the code
package adapter.objectAdapter; /** * @author Y2M * @createTime 2021/6/5 * @comment Public class Voltage220V {/** * outputs 220V */ public int output220V() { int src = 220; Println (" source voltage =" + SRC + v "); return src; }}Copy the code
package adapter.objectAdapter; /** * @author Y2M * @createTime 2021/6/5 * @comment public class VoltageAdapter implements IVoltage5V{public Voltage220V voltage220V; public VoltageAdapter(Voltage220V voltage220V) { this.voltage220V = voltage220V; } @Override public int output5V() { int dst = 0; if(null ! Int SRC = voltage220V. Output220V (); System.out.println(" use object adapter, adapt ~~"); dst = src / 44; System.out.println(" adaptation complete, output voltage =" + DST); } return dst; }}Copy the code
package adapter.objectAdapter; /** * @author Y2M * @createTime 2021/6/5 * @comment */ public class Client { public static void main(String[] args) { System.out.println(" === class adapter pattern ===="); Phone phone = new Phone(); phone.changing(new VoltageAdapter(new Voltage220V())); }}Copy the code

Object adapter pattern considerations and details

  1. Object adapters and class adapters are essentially the same idea, but implemented differently. In accordance with the principle of composite reuse, composition is used instead of inheritance, so it addresses the limitation that class adapters must inherit SRC and no longer require DST to be an interface.
  2. Cheaper to use and more flexible.

Interface adapter mode

introduce

  1. When it is not necessary to implement all the methods provided by the interface, an abstract class implementation interface can be designed first and provide a default implementation (empty method) for each method in the interface. Then the subclasses of the abstract class can selectively override some methods of the parent class to implement the requirements
  2. This applies when an interface does not want to use all of its methods.

The code analysis

package adapter.interfaceAdapter;

/**
 * @author Y2M
 * @createTime 2021/6/5
 * @comment
 */
public interface CusInterface {
    public void m1();
    public void m2();
    public void m3();
    public void m4();
}

Copy the code
package adapter.interfaceAdapter;

/**
 * @author Y2M
 * @createTime 2021/6/5
 * @comment
 */
public class AbsAdapter implements CusInterface {
    @Override
    public void m1() {

    }

    @Override
    public void m2() {

    }

    @Override
    public void m3() {

    }

    @Override
    public void m4() {

    }
}

Copy the code
package adapter.interfaceAdapter; /** * @author Y2M * @createTime 2021/6/5 * @comment */ public class Client { public static void main(String[] args) { AbsAdapter AbsAdapter = new AbsAdapter(){@override public void m1() {system.out.println (" use m1 method "); }}; absAdapter.m1(); }}Copy the code

The adapter pattern is applied in the SpringMVC framework

The HandlerAdapter in SpringMvc, for example, uses the adapter pattern, and there are multiple implementations of different processors, so the way to call it is not determined, so if you need to call the Controller method directly, When you need to call it, you have to constantly use if else to determine which subclass it is and then execute it. So if you want to extend Controller later, you have to modify the original code, which violates the OCP principle.