Welcome to follow the official wechat account: FSA Full Stack Action 👋

Introduction to the adapter pattern

Adapter patterns are structural patterns that serve as a bridge between incompatible interfaces.

  • Common types of adapters
    • Adapter pattern: If you don’t want to implement all the methods in an interface, you can create an Adapter that implements all the methods. When writing to other classes, you can inherit this Adapter class.
    • Class adapter pattern [Inheritance (old) + Implementation (new)] : When you want to transform a class into a class that satisfies a new interface, you can use the class adapter pattern by creating a new class that inherits from the original class and implements the new interface.
    • Adapter pattern for objects [combination] : When you want to transform an object into an object that satisfies another new interface, you can create an adapter class that holds an instance of the original class and calls the methods of the instance within the adapter class’s methods.
  • Application scenarios
    • The computer needs to read the data from the memory card. The card reader is the adapter
    • Daily use of the conversion head, such as power conversion head, voltage conversion head
    • The system needs to use existing classes whose interfaces do not fit the system’s needs (e.g. the InputStreamReader in the JDK is an adapter).
    • JDBC uses the adapter mode. JDBC provides a common abstract interface for clients. Each database vendor, such as SQL Server, Oracle, MySQL, etc., will develop a corresponding JDBC driver. The JDBC driver is an adapter software between the JDBC interface and the database engine interface.
  • advantages
    • You can make any two classes that are not related to each other run together, so that classes that would otherwise not work together because of incompatible interfaces can work together
    • Increase flexibility, improve reusability, the adapter class can be used in multiple systems, in line with the open closed principle
  • disadvantages
    • The call link of the whole class is increased. Originally, A can call C directly. After using the adapter, A calls B, and B calls C again

Supplement: The adapter pattern is used when the design is complete and the class and interface do not work together and need to be filled in.

Second, the adapter pattern code implementation

1. Interface adapter mode

Some interfaces have more than one abstract method, and when we write an implementation class for that interface, we have to implement all the methods of that interface, which sometimes feels redundant because we don’t need all the methods, we only need to implement part of the interface.

Create payment gateway interface:

/** * Payment gateway interface **@author GitLqr
 */
public interface IPayGateway {

	/** * order */
	void order(a);

	/**
	 * 退款
	 */
	void refund(a);

	/** * Query */
	void query(a);

	/** * send red envelopes */
	void sendRedPack(a); . }Copy the code

Create an interface adapter class:

/** * Interface adapter: provides a default implementation for all interfaces **@author GitLqr
 */
public class PayGatewayAdapter implements IPayGateway {

	@Override
	public void order(a) {}@Override
	public void refund(a) {}@Override
	public void query(a) {}@Override
	public void sendRedPack(a) {}}Copy the code

Create a concrete business class:

/** * Video VIP order: Order and refund only **@author GitLqr
 */
public class VideoVipOrder extends PayGatewayAdapter {
	@Override
	public void order(a) {
		System.out.println("Video VIP order successful");
	}

	@Override
	public void refund(a) {
		System.out.println("Video VIP refund successful"); }}Copy the code

Compared to the implementation of IPayGateway interface, inherits PayGatewayAdapter adapter class, can make VideoVipOrder code concise many.

2. The adapter pattern for the class

When you want to transform a class into a class that satisfies another new interface, you can use the class adaptor pattern to create a new class that inherits from the original class and implements the new interface.

Create an old class:

[old class] corresponds to the existing class in the project, can run stably, but does not support some new functions. In real development, these old class implementations can be quite complicated (and can’t be changed easily)!!

/** * Old class: port, only support USB **@author GitLqr
 */
public class Port {
	public void usb(Object usbDevice) {
		System.out.println("Insert USB device"); }}Copy the code

Create a new functional interface:

The [new function interface] generally has methods in the old class, to facilitate subsequent interface programming.

/** * New port: Supports more new port types (such as TypeC, USB4) as well as the old port type (USB) **@author GitLqr
 */
public interface INewPort {

	void usb(Object usbDevice);

	void typec(Object typecDevice);

	void usb4(Object usb4Device);
}
Copy the code

Create a new class:

[new class] need to inherit [old class], at the same time [new function interface]

/** * New class: Port adapter [docking] **@author GitLqr
 */
public class PortAdapter extends Port implements INewPort {

	@Override
	public void typec(Object typecDevice) {
		System.out.println("Insert type-c device");
	}

	@Override
	public void usb4(Object usb4Device) {
		System.out.println("Insert lightning 4 device"); }}Copy the code

Use:

public static void main(String[] args) {... INewPort newPort =new PortAdapter();
    newPort.usb(usbDevice); // The old function works properly
    newPort.typec(typecDevice);
    newPort.usb4(usb4Device);
}
Copy the code

3. Adapter patterns for objects

When you want to transform an object into an object that satisfies another new interface, you can create an adapter class that holds an instance of the original class and calls the instance’s methods within the adapter class’s methods.

The adapter for the object is more like a wrapper (or enhancement), and the actual function needs to be handled by the original object, such as the charger plug problem. The plug converter only changes the type of the charger plug, but it is the charger itself that actually charges the phone.

Create the charger class:

/** * Charger **@author GitLqr
 */
public class Charger {

	void charge(a) {
		System.out.println("Charging..."); }}Copy the code

Create new interface (support multiple plug conversion) :

/** * Interface: all kinds of plugs **@author GitLqr
 */
public interface IPlugConverter {

	/** * Double plug charging */
	void chargeOnTwoPin(a);

	/** * Three-pin plug charging */
	void chargeOnThreePin(a);

	/** * Three-pin plug charging (Hong Kong version) */
	void chargeOnThreePinHK(a);

}
Copy the code

Create an adapter class that satisfies the new interface:

/** * Charger plug adapter **@author GitLqr
 */
public class ChargerPlugAdapter implements IPlugConverter {

	private Charger charger;

	public ChargerPlugAdapter(Charger charger) {
		super(a);this.charger = charger;
	}

	@Override
	public void chargeOnTwoPin(a) {
		charger.charge();
	}

	@Override
	public void chargeOnThreePin(a) {
		System.out.println("Use three-pin plug");
		charger.charge();
	}

	@Override
	public void chargeOnThreePinHK(a) {
		System.out.println("Use Hong Kong version three-pin plug"); charger.charge(); }}Copy the code

If this article has been helpful to you, please feel free to follow my wechat official account: FSA Full Stack Action, which will be the biggest incentive for me. The public account not only has Android technology, iOS, Python and other articles, there may be skills you want to know oh ~