Adapter mode_Dark horse programmer study notes

Overview

If you go to European countries to travel, their sockets are on the far left as shown in the picture below, which are European standards. And the plug we use is on the far right of the picture below. Therefore, our laptops and mobile phones cannot be directly charged locally. So we need a socket converter. The first side of the converter is inserted into the local socket, and the second side is for us to charge, so that our plug can be used locally. There are many such examples in life. Mobile phone chargers (convert 220v to 5v voltage), card readers, etc., are actually using the adapter mode.

 

definition:

Converting a class's interface to another interface that the client desires enables classes that would otherwise not work together due to interface incompatibility to work together.

The adapter pattern is divided into the class adapter pattern and the object adapter pattern. The former has a higher degree of coupling between classes than the latter, and requires programmers to understand the internal structure of the relevant components in the existing component library, so the application is relatively small. 

structure

The adapter pattern (Adapter) includes the following main roles:

  • Target interface: the interface expected by the current system business, which can be an abstract class or interface.
  • Adaptee class: It is the component interface in the existing component library that is accessed and adapted.
  • Adapter class: It is a converter, which converts the adapter interface into the target interface by inheriting or referencing the object of the adapter, allowing clients to access the adapter in the format of the target interface.

class adapter pattern

Implementation method: define an adapter class to implement the business interface of the current system, and at the same time inherit the existing components (target interface) in the existing component library.

Case [Example] Card reader

An existing computer can only read the SD card, and to read the contents of the TF card, it needs to use the adapter mode. Create a card reader to read the contents of the TF card.

The class diagram is as follows:

 

Code implementation (class adapter implementation):

The target interface, the type that can be called directly by the Computer

/**
 * target interface
 * @author CharlieLiang
 *
 */
public interface SDCard {

	//Read data from SD card
	String readSD();
	//Write data to SD card
	void writeSD(String msg);
}

The implementation class of the target interface

/**
 * specific SD card
 * @author CharlieLiang
 *
 */
public class SDCardImpl implements SDCard{

	@Override
	public String readSD() {
		String msg="SDCard read msg : hello word SD";
		return msg;
	}

	@Override
	public void writeSD(String msg) {
		System.out.println("SDCard write msg: "+msg);
	}

}

Computer class, take the target interface as a parameter, write to SD card, read data

/**
 * computer class
 * @author CharlieLiang
 *
 */
public class Computer {

	//Read data from SD card
	public String readSD(SDCard sdCard) {
		if(sdCard == null) {
			throw new NullPointerException("sd card is null");
		}
		return sdCard.readSD();
	}
}

The interface of the adapter, the computer cannot call the method inside, that is, the computer cannot read or write TFCard

/**
 * Adapter class interface
 * @author CharlieLiang
 *
 */
public interface TFCard {

	//Read data from TF card
	String readTF();
	//Write data to TF card
	void writeTF(String msg);
}

The specific adapter class, the implementation class of the adapter interface

/**
 * adapter class
 * @author CharlieLiang
 *
 */
public class TFCardImpl implements TFCard{

	@Override
	public String readTF() {
		String msg="TFCard read msg :hello word TFCard";
		return msg;
	}

	@Override
	public void writeTF(String msg) {
		System.out.println("TFCard write msg :"+msg);
	}

}

client test

public class Client {

	public static void main(String[] args) {
		//Create computer object
		Computer computer =new Computer();
		
		//Read data from SD card
		String msg=computer.readSD(new SDCardImpl());
		System.out.println(msg);
		
		System.out.println("================================");
		
		//Use the computer to read the data in the TF card
		//Define the adapter class
		String msg1=computer.readSD(new SDAdapterTF());
		System.out.println(msg1);
	}
}

operation result:

illustrate:

The class adapter pattern violates the principle of composition reuse. A class adapter is available if the client class has an interface specification, but not otherwise. 

Object Adapter Pattern

Implementation: The object adapter pattern can be used to introduce (aggregate) the components already implemented in the existing component library into the adapter class, which also implements the business interface of the current system. 

Case 2: Retrofitting the card reader case with the object adapter pattern

The class diagram is as follows:

  code show as below:

/**
 * Adapter class
 * TFCard is aggregated, so that the functions of TFCard can be realized
 * implements SDCard,This allows the computer to call SDCard
 * @author CharlieLiang
 *
 */
public class SDAdapterTF  implements SDCard{

	private TFCard tfCard;
	public SDAdapterTF(TFCard tfCard) {
		this.tfCard=tfCard;
	}
	@Override
	public String readSD() {
		System.out.println("adapter read tf card");
		//Returns the data read in TFCard
		return tfCard.readTF();
	}

	@Override
	public void writeSD(String msg) {
		System.out.println("adapter write tf card");
		tfCard.writeTF(msg);
	}

}

Client:

public class Client {

	public static void main(String[] args) {
		//Create computer object
		Computer computer =new Computer();
		
		//Read data from SD card
		String msg=computer.readSD(new SDCardImpl());
		System.out.println(msg);
		
		System.out.println("================================");
		
		 //Use the computer to read the data of the TF card
		//Create the adapter class object
		SDAdapterTF sdAdapterTF =new SDAdapterTF(new TFCardImpl());
		String msg2=computer.readSD(sdAdapterTF);
		System.out.println(msg2);
	}
}

operation result:

Notice:

Another adapter mode is the interface adapter mode. When you don't want to implement all the methods in an interface, you can create an abstract class Adapter to implement all the methods. At this time, we only need to inherit the abstract class. 

Application scenarios

  • The previously developed system has classes that meet the functional requirements of the new system, but its interface is inconsistent with that of the new system.
  • Use a component provided by a third party, but the component interface definition is different from the interface definition required by yourself.

JDK source code analysis

The adaptation of Reader (character stream) and InputStream (byte stream) uses InputStreamReader.

InputStreamReader inherits from Reader in the java.io package, and provides implementation for the abstract unimplemented methods in him. Such as:

public int read() throws IOException {
    return sd.read();
}
​
public int read(char cbuf[], int offset, int length) throws IOException {
    return sd.read(cbuf, offset, length);
}

As shown in the sd (StreamDecoder class object) in the above code, in Sun's JDK implementation, the actual method implementation is the encapsulation of the call to the method of the same name of the sun.nio.cs.StreamDecoder class. The class structure diagram is as follows:

 

 

As can be seen from the above figure:

  • InputStreamReader is a package of StreamDecoder that also implements Reader.
  • StreamDecoder is not a content in the Java SE API, it is its own implementation given by Sun JDK. But we know that they encapsulate the byte stream class (InputStream) in the constructor, and decode and convert between byte stream and character stream through this class.

in conclusion:

From the surface level, InputStreamReader does the conversion between InputStream byte stream class to Reader character stream. As can be seen from the implementation class relationship structure in the above Sun JDK, the design and implementation of StreamDecoder actually adopts the adapter mode.

Tags: Design Pattern

Posted by FD_F on Fri, 20 May 2022 03:37:43 +0300