Adaptation and packaging mode application of multi system docking

Time:2022-7-28

 

In the daily development system, it is usually necessary to connect multiple systems and use the adapter mode.

For example, the payment method involves the docking of multiple systems.

International practice, first introduce the concept.

 

Adapter mode:

 

When it comes to adapters, you can naturally think of power adapters for mobile phones.

His role is to convert 220V AC into 5V DC used by mobile phones.

Adapter function: it can convert one interface into another, which has met the expectations of customers.

 

 

In the software system, for example, in phase I, we used some functional interfaces of Alibaba cloud SDK package.

But in phase II, I want to change the same function of Tencent cloud SDK. But they have the same function and different interface parameters.

We don’t want to modify our business code according to the interface of Tencent cloud. After all, the business logic has been tested and verified repeatedly. The interface of Tencent cloud can be packaged to realize a phase I interface. This job is called adaptation.

For example:

In the software system, you may have many payment methods, including wechat payment, Alipay payment, and various banks.

But their payment interfaces are certainly different. I don’t want to add a new payment method and modify the code.

At this point, we need a unified payment adapter service to help us shield the differences of various payment methods.

My business service only interacts with unified payment. Unified payment provides a unified interface to the business system. Unified payment is responsible for routing the background of different payment systems and shielding the differences of various systems. This work is also called adaptation

 

Adaptation mode:

Adaptation and packaging mode application of multi system dockingAdaptation and packaging mode application of multi system docking

/**
 *Target interface: an interface providing 5V voltage
 */
public interface V5Power
{
    public int provideV5Power();
}

/**
 *Adaptees, existing functions: household 220V AC
 */
public class V220Power
{
    /**
     *Provide 220V voltage
     */
    public int provideV220Power()
    {
        System.out.println ("I provide 220V AC voltage.");
        return 220 ; 
    }
}

/**
 *Adapter, with existing object and function implementation interface, turns 220V voltage into 5V
 */
public class V5PowerAdapter implements V5Power
{
    /**
     *Combination mode
     */
    private V220Power v220Power ;
    
    public V5PowerAdapter(V220Power v220Power)
    {
        this.v220Power = v220Power ;
    }
 
    @Override
    public int provideV5Power()
    {
        int power = v220Power.provideV220Power() ;
        //Power goes through various operations -- >5 
        System.out.println ("adapter: I quietly adapted the voltage.");
        return 5 ; 
    } 
    
}

Adapter

Adaptation and packaging mode application of multi system dockingAdaptation and packaging mode application of multi system docking

public class Mobile
{
    //Use target interface function
    public void inputPower(V5Power power)
    {
        int provideV5Power = power.provideV5Power();
        System.out. Println ("mobile phone (client): I need 5V voltage to charge, now it is -- >" + providev5power + "V");
    }
}

//Testing
public class Test
{
    public static void main(String[] args)
    {
        Mobile mobile = new Mobile();
        V5Power v5Power = new V5PowerAdapter(new V220Power()) ; 
        mobile.inputPower(v5Power);
    }
}

Test

definition:

Convert the interface of a class into another interface expected by the customer. Adapters allow classes with incompatible interfaces to cooperate seamlessly.

The popular point of adaptation mode is to use an existing function class to implement an interface. In this way, the function class and the original client code do not need to be changed. For the client, it is equivalent to changing an implementation method.

The advantage is to let the customer [decouple] from the implementation. Next time I change other function classes, I will write another adapter. It’s a bit like changing an implementation class in the policy mode.

 

Of course, our adapter can wrap many adapted objects, that is, we can combine many existing functional classes. Because many interfaces are complex, many classes need to be used.

Similarly, the adapter can also use inheritance instead of combination object.

 

Example:

Previously, Java collection classes have implemented the enumeration enumeration interface, which can traverse each element in the collection without knowing how they are managed in the collection.

Later, a new iterator iterator interface was introduced. This interface is very similar to the enumeration interface, which allows you to traverse each element in the collection.

The difference is that iterators also provide the ability to delete elements.

Facing the legacy code, what these codes expose is the enumeration interface. They are the old version of Java, which only supports enumeration, but we hope to use iterators in the new code. Only one iterator can be implemented with enumeration.

Adaptation and packaging mode application of multi system dockingAdaptation and packaging mode application of multi system docking

public class EnumerationIterator implements Iterator{
    Enumeration enum;
    
    public EnumerationIterator(Enumeration enum){
        this.enum = enum;
    }
    
    public boolean hasNext(){
        return enum.hasMoreElements();
    }
    
    public Object next(){
        return enum.nextElement();
    }
    
    public void remove(){
        throw new UnsupportedOperationException();
    }

}
/*
The enumeration interface is read-only. The adapter cannot implement a remove () method with actual functions. Our implementation method is not perfect. Customers must be careful of potential exceptions. As long as the customer is careful enough and explains in the adapter's documentation, this is also a reasonable solution.

*/

Implementing iterators with enumerations

 

Appearance mode:

 

Appearance mode: provide a unified interface to access a group of interfaces in the subsystem. Appearance defines a high-level interface, which makes the subsystem easier to use.

For example, with the click of our remote control, we will automatically open the curtain, turn on the projector, turn on the stereo, and start playing the movie. Instead of doing it step by step.

It not only simplifies the interface, but also decouples customers from the build summary.

The purpose is to make the system easier to use and comply with the principle of [know at least], because the customer has only one friend of [appearance role].

 

[at least know] the principle is not to allow too many classes to be coupled together, so as not to affect the whole body when modifying the system. Try to “make fewer friends”. The interaction related to yourself is enough.

As far as an object is concerned, within the method of the object, we should only call methods belonging to the following scope:

1. The object itself

2. Objects passed in as parameters of methods

3. Any object created or instantiated by this method

4. Any component of the object, that is, the object referenced by the attribute variable

If you call a method that returns an object, it is equivalent to making a request to a sub part of another object. We rely on one more object.

//Do not apply the principle of [least know]

public float getTemp(){

  Thermometer thermometer = station.getThermometer();

return thermometer. getTemperature(); // We obtained the thermometer object from the weather station, and then obtained the temperature from this object.

}

//Apply the [least known] principle

public float getTemp(){

return station. getTemperature(); // I should ask the weather station to give me the temperature directly. I don’t want to rely on the thermometer object.

}

 

Decoration mode:

 

The beverage is described in an object-oriented way. The limitation of this description is.

We can add excipients to our drinks. For example: large cup, iced, milk, double coffee.

We can’t build a class with one combination. Then the number of classes will explode.

At this time, it is very difficult to calculate the price.

Put various spices in the base class. Seasoning can be Boolean or data or enumeration type.

When calculating the price of each drink, it depends on whether or how many of these condiments are available.

Adaptation and packaging mode application of multi system dockingAdaptation and packaging mode application of multi system docking

public class Drink{
    private boolean milk;
    private boolean sugar;
    
    public double cost(){
        double price = 0d;
        if(milk){ price +=0.5; }
        if(sugar){price +=0.1; }
        return price;
    } 
    
    public void addMilk(){
        this.mocha=true;
    }
    
    public void addSugar(){
        this.whip= true;
    }
}

public class DarkCoffee extends Drink{
    public double cost(){
        double price = super.cost();
        price += 2.0;
        return price;
    }

}


 Test:
public class Test{

    public static void main(String[] args){
        Drink coffee = new DarkCoffee();
        coffee.addMocha();
        coffee.addWhip();
        System.out.println(coffee.cost());
    }
}

Solve the seasoning problem by setting properties

There are problems with this design:

1. If there are many condiments, the drink category is very large, and the new and deleted condiments need to be modified, and the price of condiments needs to be adjusted.

2. In the case of double seasoning, the Boolean value cannot be satisfied.

3. Many spices are mutually exclusive. For example, icecoffee cannot add Mocha, but it still inherits the addmocha () method of the parent class. This method is not applicable to him. He must override this method to do nothing.

It does not conform to the [opening and closing principle]

 

Decoration mode explanation:

Condiments can be used to pack basic drinks. Because the decorator and the decorated have the same super type, they can be used in the form of dolls all the time.

The decorator can add his own behavior before and after the entrusted decorator’s behavior to achieve a specific purpose.

Calculating the price is similar to recursion, which constantly delegates to the parent class, and finally unified backtracking.

Adaptation and packaging mode application of multi system dockingAdaptation and packaging mode application of multi system docking

abstract class Drink{
    public String description = "Unknown beverage";
    
    public String getDescription(){
        return description;
    }
    
    public abstract double cost();
}

//Decoration
 abstract class CondimentDecorator extends Drink{
    public abstract String getDescription();
}

//Beverages
 class DarkCoffee extends Drink{
    public DarkCoffee(){
        this.description = "DarkCoffee";
    }
    public double cost(){
        return 1.99;
    }
}

//Packaging: seasoning
 class Sugar extends CondimentDecorator{
    Drink drink;
    
    public Sugar(Drink drink){
        this.drink = drink;
    }
    
    public String getDescription(){
        return drink.getDescription() + ", add sugar";
    }
    
    public double cost(){
        return .20 + drink.cost();
    }
}

//Testing
 class Test{
    public static void main(String[] args){
        Drink drink = new DarkCoffee();
        drink = new Sugar(drink);
        //Add double sugar
        drink = new Sugar(drink);
        System.out.println(drink.getDescription() + " ,$"+drink.cost());
        //Output: darkcoffee, add sugar, add sugar, $2.39
    }
}

Decoration mode

Adaptation and packaging mode application of multi system dockingAdaptation and packaging mode application of multi system docking

public interface Drink{
    public double cost();
}

public class DarkCoffee implements Drink{
    public double cost(){
        return 2.5;
    }
}


public class Decorator implements Drink{
    private Drink drink;
    
    public Decorator (Drink drink){
        this.drink= drink;
    }
    
    public double cost(){
        return drink.cost();
    }
}

public class Sugar extends Decorator {

    public Sugar (Drink drink){
        super(drink);
    }
    
    public double cost(){
        return super.cost() + 0.1;
    }

}

Decoration mode 2

 

 

Decoration mode:Dynamically attach responsibilities to objects. To expand functions,Decorators offer a more flexible alternative than inheritance.

Decorator mode is easy to cause a large number of subcategories in design. Too many. It’s easy to confuse people. For example: java.io

 

Adaptation and packaging mode application of multi system dockingAdaptation and packaging mode application of multi system docking

/*
 Write a decorator to convert all uppercase characters in the input stream to lowercase.
We need to expand InputStream.
  */
public class LowerCaseInputStream extends FilterInputStream {

    public LowerCaseInputStream(InputStream in) {
        super(in);
    }
 
    public int read() throws IOException {
        int c = in.read();
        return (c == -1 ? c : Character.toLowerCase((char)c));
    }
        
    public int read(byte[] b, int offset, int len) throws IOException {
        int result = in.read(b, offset, len);
        for (int i = offset; i < offset+result; i++) {
            b[i] = (byte)Character.toLowerCase((char)b[i]);
        }
        return result;
    }
}


public class InputTest {
    public static void main(String[] args) throws IOException {
        int c;
        InputStream in = null;
        try {
            in = 
                new LowerCaseInputStream( 
                    new BufferedInputStream(
                        new FileInputStream("test.txt")));

            while((c = in.read()) >= 0) {
                System.out.print((char)c);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (in != null) { in.close(); }
        }
        System.out.println();
        try (InputStream in2 = 
                new LowerCaseInputStream(
                    new BufferedInputStream(
                        new FileInputStream("test.txt")))) 
        {
            while((c = in2.read()) >= 0) {
                System.out.print((char)c);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Self packaging IO

For example, we intercept and process HttpServletRequest to filter request parameters.

Adaptation and packaging mode application of multi system dockingAdaptation and packaging mode application of multi system docking

1).  The servlet API provides an httpservletrequestwrapper class to wrap the original request object,
The httpservletrequestwrapper class implements all methods in the HttpServletRequest interface, 
The internal implementation of these methods only calls the corresponding method of the wrapped request object

//The wrapper class implements the ServletRequest interface 
public class ServletRequestWrapper implements ServletRequest {

        //The wrapped ServletRequest object
        private ServletRequest request;
    
    //Constructor passes in ServletRequest implementation class object
        public ServletRequestWrapper(ServletRequest request) {
        if (request == null) {
         throw new IllegalArgumentException("Request cannot be null"); 
        }
        this.request = request;
        }

    //The specific method to implement ServletRequest: call the method implementation of the wrapped member variable. 
        public Object getAttribute(String name) {
        return this.request.getAttribute(name);
    }

        public Enumeration getAttributeNames() {
        return this.request.getAttributeNames();
    } 
    
    //...    
}    


2).  Function: used to modify or enhance a method of HttpServletRequest or httpservletresponse

public class MyHttpServletRequest extends HttpServletRequestWrapper{

    public MyHttpServletRequest(HttpServletRequest request) {
        super(request);
    }
    
    @Override
    public String getParameter(String name) {
        String val = super.getParameter(name);
        if(val != null && val.contains(" fuck ")){ 
            val = val.replace("fuck", "****");
        }
        return val;
    }
}

3).  Use: in filter, replace the incoming HttpServletRequest with myhttpservletrequest

HttpServletRequest req = new MyHttpServletRequest(request);
filterChain.doFilter(req, response);

Enhance HttpServletRequest

For example: print time before and after a method

Adaptation and packaging mode application of multi system dockingAdaptation and packaging mode application of multi system docking

//Interface
public interface Dao {
    public void insert();
    public void delete();
    public void update();
}
//Basic implementation class
public class DaoImpl implements Dao {

    @Override
    public void insert() {
        System.out.println("DaoImpl.insert()");
    }

    @Override
    public void delete() {
        System.out.println("DaoImpl.delete()");
    }

    @Override
    public void update() {
        System.out.println("DaoImpl.update()");
    }
}

//Packaging
public class LogDao implements Dao {

    private Dao dao;

    public LogDao(Dao dao) {
        this.dao = dao;
    }

    @Override
    public void insert() {
        System.out. Println ("insert() method start time:" + system. Currenttimemillis());
        dao.insert();
        System.out. Println ("insert() method end time:" + system. Currenttimemillis());
    }

    @Override
    public void delete() {
        dao.delete();
    }

    @Override
    public void update() {
        System.out. Println ("update() method start time:" + system. Currenttimemillis());
        dao.update();
        System.out. Println ("update() method end time:" + system. Currenttimemillis());
    }

}

//When calling Dao Dao = new logdao (New daoimpl());
//For the caller, he only knows that Dao is called, but he doesn't know that logging function is added
//Problem: 1. The logic of the output log cannot be reused; 2. The input log is coupled with the business logic.

Make a log before and after the decoration mode method

 

Another very similar to the decoration mode is the agent mode:

Agent mode:

Provide a stand in or placeholder for another object to control access to this object.

 

The typical feature of proxy mode is to intercept the method calls made by the client to the subject. Then do your own processing.

We usually use factory mode to return the proxy object of the corresponding object.

 

In fact, decoration mode and proxy mode are very similar to adapter mode. It is to wrap an object, and then use the function of this object to figure out the methods provided by the point.

Decoration mode

proxy pattern

Adapter mode

Appearance mode

Purpose: do not change the interface and join the responsibility

Purpose: to control the access of objects

Purpose: to convert one interface to another

Purpose: make the interface simple

Decorator mode allows new behaviors and responsibilities to be added to the design. There is no need to modify the existing code.
That is: the method is still the original method, but add something before and after the original method.

Proxy objects represent objects, not just adding actions to objects.
It is a substitute for the real theme, which can protect the unwanted access of objects.
You can also avoid hanging the GUI during loading large objects
Or hide the fact of remote calls.

It is not necessary to wrap an object, and remote calls do not wrap objects.

Agents rarely pack many layers like decorative patterns.

Several classes can be integrated to provide the interfaces required by customers.
Wrap an incompatible interface object into a compatible object.

 

When a method call is delegated to the decorator,
I don’t know how many other decorators have handled this call.

Decorators are a bit like recursive dolls. You don’t know what level they are currently on.

 

You can use new libraries and subsets without changing any code. The adapter will be wrapped for you according to the original interface.

 

Expanding the behavior and responsibility of the packaging object is not a simple transmission

 

The interface must be installed and replaced.

 

 

 

Example: multi payment system solution

By adding the adapter mode, the order service no longer calls the external payment interface when making payment, but the “payment method” interface, which is decoupled from the external system.

As long as the “payment method” interface is stable, the order service is stable. For example:

When the payment interface of Alipay is changed, the impact is limited to the Alipay adapter;

When the wechat payment interface is changed, the impact is limited to the wechat payment adapter;

When you want to add a new payment method, you only need to write a new adapter.

No matter what kind of change in the future, the scope of the code to be modified is reduced, the maintenance cost is naturally reduced, and the code quality is improved.

 

Question:

In the process of dividing micro services, it is often tangled whether it is necessary to abstract a proxy service from external functions. Specially responsible for docking with a manufacturer.

According to the concept of adapter, if the proxy service can abstract the standard interface, it is necessary to be independent. Core business services only interact with proxy services, which shield the differences between external vendors.

There will be changes in the manufacturer in the future, and our modification scope will be controlled within the agency service, which will not involve core business services.

 

For example, we usually develop a unified payment service, which interfaces with various payment systems and internally provides standard payment interfaces. Business services only interact with unified payment.

At the same time, unified payment can also help us deal with reconciliation, automatic refund after expiration and other functions. Make the business system stable and portable.

 

This article is from the blog Park, written by wanglifeng. Please indicate the original link if you reprint it:https://www.cnblogs.com/wanglifeng717/p/16348529.html

Recommended Today

Windows terminal uses nushell+oh-my-posh to beautify

First look at the renderings Please point out if the steps are wrong. Install nushell from github Download from github releaseRelease 0.66.2 · nushell/nushell (github.com) github release download speed may be slow, you can download it hereDownload (serctl.com) Install windows terminal in microsoft store Install oh-my-posh on Microsoft Store Winget can also be used, but […]