Using the Adapter Pattern

1. The use of adapter mode

1.1 Introduction

Convert the interface of a class to another interface that the client wants, so that those classes that could not work together due to incompatible interfaces can work together.

Examples : mobile phone chargers (converting 220v to 65v voltage), card readers, laptop chargers, etc., are actually using the adapter mode.

1.2 Adapter pattern structure

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

1.3 class adapter pattern

实现方式: Define an adapter class to implement the business interface of the current system , and at the same time inherit the existing components in the existing component library.

1.3.1 Class Diagram of Class Adapter Pattern

An existing computer can only read the SD card, but if you want to read the content in the TF card, you need to use the adapter mode. Create a card reader to read the contents of the TF card.

insert image description here

1.3.2 Code

The Class Adapter pattern violates the principle of compositional reuse . A class adapter is available if the client class has an interface specification, and not otherwise.

/**
 * 适配者类的接口
 */
public interface TFCard {
    
    
    // 从TF卡中读取数据
    String readTF();
    // 往TF卡中写数据
    void writeTF(String msg);
}

/**
 * 适配者类
 */
public class TFCardImpl implements TFCard {
    
    
    public String readTF() {
    
    
        String msg = "TFCard read msg : I am TFcard";
        return msg;
    }
    public void writeTF(String msg) {
    
    
        System.out.println("TFCard write msg :" + msg);
    }
}

/**
 * 目标接口
 */
public interface SDCard {
    
    
    // 从SD卡中读取数据
    String readSD();
    // 往SD卡中写数据
    void writeSD(String msg);
}

/**
 * 具体的SD卡
 */
public class SDCardImpl implements SDCard {
    
    
    public String readSD() {
    
    
        String msg = "SDCard read msg :I am SD";
        return msg;
    }
    public void writeSD(String msg) {
    
    
        System.out.println("SDCard write msg :" + msg);
    }
}

/**
 * 适配器类
 */
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);
    }
}

/**
 * 电脑类读取SD卡
 */
public class Computer {
    
    
    // 从SD卡中读取数据
    public String readSD(SDCard sdCard) {
    
    
        if(sdCard == null) {
    
    
            throw  new NullPointerException("读卡错误,请检查SD卡是否插入");
        }
        return sdCard.readSD();
    }
}

/**
 * 客户:Client
 */
public class Client {
    
    
    public static void main(String[] args) {
    
    
        // 创建电脑对象
        Computer computer = new Computer();
        // 未定义适配器类,电脑只能读取SD卡中的数据
        String msg = computer.readSD(new SDCardImpl());
        System.out.println(msg);

        // 定义适配器类,使用该电脑读取TF卡中的数据
        String msg1 = computer.readSD(new SDAdapterTF());
        System.out.println(msg1);
    }
}

// 输出结果:
// SDCard read msg :I am SD
// adapter read tf card...
// TFCard read msg : I am TFcard

1.4 Object Adapter Pattern

实现方式: The object adapter mode can be used to import the implemented components in the existing component library into the adapter class, which simultaneously realizes the business interface of the current system.

1.4.1 Object Adapter Pattern Class Diagram

An existing computer can only read the SD card, but if you want to read the content in the TF card, you need to use the adapter mode. Create a card reader to read the contents of the TF card.

insert image description here

1.4.2 Code

The adapter pattern is the interface adapter pattern . When you don't want to implement all the methods in an interface, you can create one 抽象类Adapter and implement all the methods. At this time, we only need to inherit the abstract class .

/**
 * 适配者类的接口
 */
public interface TFCard {
    
    
    // 从TF卡中读取数据
    String readTF();
    // 往TF卡中写数据
    void writeTF(String msg);
}

/**
 * 适配者类
 */
public class TFCardImpl implements TFCard {
    
    
    public String readTF() {
    
    
        String msg = "TFCard read msg : I am TFcard";
        return msg;
    }
    public void writeTF(String msg) {
    
    
        System.out.println("TFCard write msg :" + msg);
    }
}

/**
 * 目标接口
 */
public interface SDCard {
    
    
    // 从SD卡中读取数据
    String readSD();
    // 往SD卡中写数据
    void writeSD(String msg);
}

/**
 * 具体的SD卡
 */
public class SDCardImpl implements SDCard {
    
    
    public String readSD() {
    
    
        String msg = "SDCard read msg :I am SD";
        return msg;
    }
    public void writeSD(String msg) {
    
    
        System.out.println("SDCard write msg :" + msg);
    }
}

/**
 * 适配器类
 */
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);
    }
}

/**
 * 电脑类读取SD卡
 */
public class Computer {
    
    
    // 从SD卡中读取数据
    public String readSD(SDCard sdCard) {
    
    
        if(sdCard == null) {
    
    
            throw  new NullPointerException("读卡错误,请检查SD卡是否插入");
        }
        return sdCard.readSD();
    }
}

/**
 * 客户:Client
 */
public class Client {
    
    
    public static void main(String[] args) {
    
    
        // 创建电脑对象
        Computer computer = new Computer();
        // 未定义适配器类,电脑只能读取SD卡中的数据
        String msg = computer.readSD(new SDCardImpl());
        System.out.println(msg);

        // 创建适配器类对象,使用该电脑读取TF卡中的数据
        SDAdapterTF sdAdapterTF = new SDAdapterTF(new TFCardImpl());
        String msg1 = computer.readSD(sdAdapterTF);
        System.out.println(msg1);
    }
}

// 输出结果:
// SDCard read msg :I am SD
// adapter read tf card...
// TFCard read msg : I am TFcard

1.5 Application scenarios

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

1.6 JDK source code analysis

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

1.6.1 Conversion class diagram of byte stream to character stream

InputStreamReader is an encapsulation of StreamDecoder which also implements Reader. StreamDecoder is not part of the 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 use this class to perform decoding conversion between byte stream and character stream.

insert image description here

1.6.2 Partial source code analysis

InputStreamReader inherits from Reader in the java.io package, and implements the abstract unimplemented methods in it. sd (StreamDecoder class object), in Sun's JDK implementation, the actual method implementation is the call encapsulation of the method with the same name of the sun.nio.cs.StreamDecoder class.

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);
}

1.6.3 Summary

From the superficial point of view, InputStreamReader converts the InputStream byte stream class to the Reader character stream. It can be seen from the implementation class relationship structure in Sun JDK above that the design and implementation of StreamDecoder actually adopts the adapter mode .

记录每一个学习瞬间

Guess you like

Origin blog.csdn.net/qq_51601665/article/details/131110627