In a moment, the topic body of personal space design pattern goes deep into MyBatis source code to understand the adapter pattern of Java design pattern

What is adapter mode

Definition: transform the interface of a system into another form, so that the interface that cannot be called directly can be called.

Adapter pattern role division

The adapter pattern involves three roles:
1. Adapter: the object or type to be adapted, equivalent to the plug.
2. Adapter: the intermediate object connecting the target and the source, which is equivalent to the plug converter.
3. Target: the expected target, equivalent to the socket.
There are three types of adapter patterns: class adapter pattern, object adapter pattern, interface adapter pattern (or default adapter pattern).

Adapter mode application scenario

1. Compatibility of interface between new and old versions
 2. The integration of various log frameworks in Mybatis

How the adapter is created

1. Object adapter (combination mode)
2. Class adapter (inheritance mode)

Adapter quick start example

For example, in the earlier version of V1, the order interface input parameter was Map type. With the update and iteration of business, the order interface input parameter needs to support the List type in V2? How to support List type without changing the interface code.

1. Adapter: the object or type to be adapted, equivalent to the plug.

public void froOrderMap(Map map) {
    for (int i = 0; i < map.size(); i++) {
        // Use I as MapKey to get data
        String value = (String) map.get(i);
        System.out.println("value:" + value);
    }
}

2. Target: the expected target, equivalent to the socket.

public interface List<E> extends Collection<E> {
    ......
    int size();
    E get(int index);
    E set(int index, E element);
}

3. Adapter: the intermediate object connecting the target and the source, equivalent to the plug converter

public class ListAdapter extends HashMap {

    private List list;
    public ListAdapter(List list) {
        this.list = list;
    }
    @Override
    public int size() {
        return list.size();
    }
    @Override
    public Object get(Object key) {
        return list.get(Integer.valueOf(key.toString()).intValue());
    }
}

Test operation effect

public class Test {
    public static void main(String[] args) {
        // 1. Get collection type user
        List member = new MemberService().getMember();
        //new OrderService().froOrderMap(member);
        ListAdapter listAdapter = new ListAdapter(member);
        new OrderService().froOrderMap(listAdapter);
    }
}

Using adapter mode to collect logs

For example, when designing a log collection system, you may consider file writing, MQ writing, database writing, etc.

Object adapter implementation

Define basic entity class

@Data
public class LogBean {
    /**
     * Log ID
     */
    private String logId;
    /**
     * Log content
     */
    private String logText;
}

1. Source target interface

public interface LogWriteFileService {

    /**
     * Write log to file
     */
    void logWriteFile();
    /**
     * Read log from local file
     *
     * @return
     */
    List<LogBean> readLogFile();
}

1. Source target interface implementation class

public class LogWriteFileServiceImpl implements LogWriteFileService {
    @Override
    public void logWriteFile() {
        System.out.println(">>>Write log to file...");
    }
  @Override
    public List<LogBean> readLogFile() {
        LogBean log1 = new LogBean();
        log1.setLogId("0001");
        log1.setLogText("Tomcat Startup success..");

        LogBean log2 = new LogBean();
        log2.setLogId("0002");
        log2.setLogText("Jetty Startup success..");
        List<LogBean> listArrayList = new ArrayList<LogBean>();
        listArrayList.add(log1);
        listArrayList.add(log2);
        return listArrayList;
    }
}

2. Target interface

public interface LogWriteDbService {

    /**
     * Write log to database
     */
   public void writeDbFile(LogBean logBean);
}

2. adapter

//LogAdapter: adapter
//LogWriteDbService: target
public class LogAdapter implements LogWriteDbService {
    //Source interface
    private LogWriteFileService logWriteFileService;

    public LogAdapter(LogWriteFileService logWriteFileService) {
        this.logWriteFileService = logWriteFileService;
    }

    @Override
    public void writeDbFile(LogBean logBean) {
        // 1. Read the log file from the file
        List<LogBean> logBeans = logWriteFileService.readLogFile();
        //target
        // 2. Write to database
        logBeans.add(logBean);
        System.out.println(">>>Write data to database..");
        // 3. Write to local file
        logWriteFileService.logWriteFile();
    }
}

Advantages and disadvantages of adapter mode

Advantages of adapter mode
 Better reusability 
The system needs to use existing classes, and the interface of this class does not meet the needs of the system. Then through the adapter pattern, these functions can be better reused. 
Better scalability 
When implementing the function of the adapter, you can call the function developed by yourself, so as to naturally expand the function of the system. 

Disadvantages of adapter mode
 Excessive use of adapters will make the system very messy and difficult to grasp as A whole. For example, it is obvious that the A interface is called, but in fact, it is internally adapted to the B interface implementation. If there are too many such cases in A system, it is no different from A disaster. So if it's not necessary, you can refactor the system directly instead of using the adapter.

Mbatis log collection and analysis

There are many log frameworks commonly used in Java development, such as Log4j, Log4j2, slf4j, etc. Mybatis has defined a set of unified log interfaces for the upper layer to use, and provided corresponding adapters for the above common log frameworks

In the Log module of Mybatis, Adapter mode is used. When using the Log module internally, Mybatis uses its internal interface org.apache.ibatis.logging.Log, but the external interfaces of the common Log framework are different. In order to reuse and integrate these third-party Log components, Mybatis provides a variety of adapters in its Log module, which adapts these external interfaces to org.apache.ibatis.logging.Log, so Mya Btis can call the third-party logs through the Log interface

Source code analysis chart

Source code analysis

Mybatis Log interface: equivalent to the source interface

package org.apache.ibatis.logging;

public interface Log {
  boolean isDebugEnabled();
  boolean isTraceEnabled();
  void error(String s, Throwable e);
  void error(String s);
  void debug(String s);
  void trace(String s);
  void warn(String s);
}

Mybatis source interface implementation class

Adapter type I

package org.apache.ibatis.logging.slf4j;

import org.apache.ibatis.logging.Log;
import org.slf4j.Logger;

//Slf4jLoggerImpl: equivalent to adapter
//Log: equivalent to the source interface
class Slf4jLoggerImpl implements Log {

  //Logger: equivalent to the target interface
  private Logger log;

  public Slf4jLoggerImpl(Logger logger) {
    //Source = target
    log = logger;
  }

Adapter type II

package org.apache.ibatis.logging.log4j2;

import org.apache.ibatis.logging.Log;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.spi.AbstractLogger;
//Log4j2Impl: equivalent to adapter
//Log: equivalent to the source interface
public class Log4j2Impl implements Log {
  
  private Log log;
  //constructor
  public Log4j2Impl(String clazz) {
    //Target interface
    Logger logger = LogManager.getLogger(clazz);
    //Judgment type to achieve: equivalent to goal
    if (logger instanceof AbstractLogger) {
      log = new Log4j2AbstractLoggerImpl((AbstractLogger) logger);
    } else {
      //Source = target
      log = new Log4j2LoggerImpl(logger);
    }
  }

Target interface: Logger

Knowledge sharing

Reference: ant class: http://www.mayikt.com

Published 23 original articles, won praise 5, visited 10000+
Private letter follow

Tags: Apache Mybatis Database log4j

Posted on Tue, 14 Jan 2020 19:06:39 -0800 by ron8000