1 Overview
Adapter mode: convert the interface of a class into another interface desired by the requirements, so that those classes that cannot work together due to interface incompatibility can work together
classification
- The class adapter pattern class has a high degree of coupling
- Object Adapter Pattern
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 the target interface by inheriting or referencing the adapter object, so that customers can access the adapter according to the format of the target interface.
Type 3 adapter mode
Demand objectives:
Define an adapter class to implement the business interface of the current system and inherit the existing components in the existing component library
This mode can be used if you want to read the new TF Card in order to read the SD card by the computer
Computer
public class Computer { public String readSD(SDCard sdCard) { if(sdCard == null) { throw new NullPointerException("sd card null"); } return sdCard.readSD(); } }
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 = "read SDCard"; return msg; } public void writeSD(String msg) { System.out.println("write msg : " + msg); } }
TF card interface
public interface TFCard { // Method of reading TF Card String readTF(); // Write TF card function void writeTF(String msg); }
TF implementation class
public class TFCardImpl implements TFCard { public String readTF() { String msg ="read TFCard"; return msg; } public void writeTF(String msg) { System.out.println("write msg : " + msg); } }
adapter class
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)); } } /* Operation results: read SDCard ------------ adapter read tf card read TFCard */
As mentioned above, 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
Demand objectives:
The object adapter mode can introduce the implemented components in the existing component library into the adapter class, which implements the business interface of the current system at the same time
Retrofit adapter class
adapter class
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)); } } /* Operation results: read SDCard ------------ adapter read tf card read TFCard */
In addition, 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
Interface adapter mode
A interface
public interface A { String read(); void write(); String listen(); }
Abstract class B
public abstract class B implements A { @Override public String read() { System.out.println("Read data"); return null; } @Override public void write() { } @Override public String listen() { return null; } }
Implementation class C
public class C extends B { @Override public String read() { return super.read(); } }
5 usage 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 the components provided by the third party, but the component interface definition is different from that required by yourself.
6 JDK source code analysis
The adaptation of Reader (character stream) and InputStream (byte stream) uses inputstreamreader, which inherits from Java The reader in the IO package gives the implementation of the abstract and unimplemented methods
From the code:
- 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 InputStream class in the construction method, and decode and convert between byte stream and character stream through this class
InputStreamReader converts 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