0. Ma Xian inspirational
Have a dream, even if it is far away.
1. General
If you travel to European countries, their sockets are shown on the far left of the figure below, which is the European standard. The plug we use is shown on the far right in the figure below. Therefore, our laptops and mobile phones cannot be directly charged locally. Therefore, 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 examples in life, such as mobile phone charger (converting 220v to 5v voltage), card reader, etc. in fact, the adapter mode is used.
definition:
Convert the interface of a class into another interface desired by the customer, so that those classes that cannot work together due to incompatible interfaces can work together.
Adapter mode is divided into class adapter mode and object adapter mode. The former has higher coupling between classes than the latter, and requires programmers to understand the internal structure of relevant components in the existing component library, so there are relatively few applications.
2. Structure
The Adapter pattern contains the following main roles:
- Target interface: the interface expected by the current system business. It can be an abstract class or interface.
- Adapter class: it is the component interface in the existing component library accessed and adapted.
- Adapter class: it is a converter that converts the adapter interface into a target interface by inheriting or referencing the adapter object, so that customers can access the adapter in the format of the target interface.
3. Class adapter mode
Implementation method: define an adapter class to implement the business interface of the current system and inherit the existing components in the existing component library.
Card reader
An existing computer can only read the SD card, and to read the contents of the TF card, you need to use the adapter mode. Create a card reader to read the contents of the TF card.
Class diagram is as follows:
The code is as follows:
//SD card interface public interface SDCard { //Method of reading SD card String readSD(); //Write SD card function void writeSD(String msg); } //SD card implementation class public class SDCardImpl implements SDCard { public String readSD() { String msg = "sd card read a msg :hello word SD"; return msg; } public void writeSD(String msg) { System.out.println("sd card write msg : " + msg); } } //Computer public class Computer { public String readSD(SDCard sdCard) { if(sdCard == null) { throw new NullPointerException("sd card null"); } return sdCard.readSD(); } } //TF card interface public interface TFCard { //Method of reading TF Card String readTF(); //Write TF card function void writeTF(String msg); } //TF Card implementation class public class TFCardImpl implements TFCard { public String readTF() { String msg ="tf card read msg : hello word tf card"; return msg; } public void writeTF(String msg) { System.out.println("tf card write a msg : " + msg); } } //Define adapter class (SD compatible TF) public class SDAdapterTF extends TFCardImpl implements SDCard { public String readSD() { System.out.println("adapter read tf card "); return readTF(); } public void writeSD(String msg) { System.out.println("adapter write tf card"); writeTF(msg); } } //Test class public class Client { public static void main(String[] args) { Computer computer = new Computer(); SDCard sdCard = new SDCardImpl(); System.out.println(computer.readSD(sdCard)); System.out.println("------------"); SDAdapterTF adapter = new SDAdapterTF(); System.out.println(computer.readSD(adapter)); } }
The class adapter pattern violates the principle of composite reuse. Class adapter is available when the client class has an interface specification, otherwise it is not available.
4. Object adapter mode
Implementation method: the object adapter mode can introduce the implemented components in the existing component library into the adapter class, which also implements the business interface of the current system.
Card reader
We use the object adapter pattern to rewrite the reader case. Class diagram is as follows:
The code is as follows:
For the code of class adapter pattern, we only need to modify the adapter class (SDAdapterTF) and test class.
//Create adapter object (SD compatible TF) public class SDAdapterTF implements SDCard { private TFCard tfCard; public SDAdapterTF(TFCard tfCard) { this.tfCard = tfCard; } public String readSD() { System.out.println("adapter read tf card "); return tfCard.readTF(); } public void writeSD(String msg) { System.out.println("adapter write tf card"); tfCard.writeTF(msg); } } //Test class public class Client { public static void main(String[] args) { Computer computer = new Computer(); SDCard sdCard = new SDCardImpl(); System.out.println(computer.readSD(sdCard)); System.out.println("------------"); TFCard tfCard = new TFCardImpl(); SDAdapterTF adapter = new SDAdapterTF(tfCard); System.out.println(computer.readSD(adapter)); } }
Note: another Adapter mode is the interface Adapter mode. When you do not 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.
5. 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.
- Components provided by a third party are used, but the component interface definition is different from that required by itself.
6.JDK source code analysis
The adaptation of Reader (character stream) and InputStream (byte stream) uses InputStreamReader.
InputStreamReader inherits from the Reader in the java.io package and implements the abstract unimplemented methods in it. For example:
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); }
sd (StreamDecoder class object) in the above code. In Sun's JDK implementation, the actual method implementation is the call encapsulation of the method with the same name of sun.nio.cs.StreamDecoder class. Class structure diagram is as follows:
As can be seen from the above figure:
- InputStreamReader encapsulates the StreamDecoder that also implements the Reader.
- StreamDecoder is not the content of Java SE API, but its own implementation given by Sun JDK. But we know that they encapsulate the byte stream class (InputStream) in the construction method, and decode and convert between byte stream and character stream through this class.
Conclusion:
From the surface level, InputStreamReader does the conversion from InputStream byte stream class to Reader character stream. As can be seen from the implementation class relationship structure in Sun JDK above, the design and implementation of StreamDecoder actually adopts the adapter mode.
This blog comes from the summary of dark horse programmer's video tutorial and the arrangement of notes. It is only for learning and communication. It should not be used for commercial purposes. If there is infringement, please contact the blogger to delete it. Blogger QQ: 194760901