• 周六. 10 月 5th, 2024

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

Design pattern: adapter pattern closely related to spring MVC

King Wang

1 月 3, 2022

List of articles

    • Preface
    • Adapter pattern
      • 1、 Definition
      • 2、UML Class diagram
      • 3、 Practical examples
      • 4、 summary
        • 1) advantage
        • 2) shortcoming
        • 3) Applicable scenario
    • SpringMVC The underlying adapter pattern
    • Reference resources

Preface

The adapter pattern is one of the most common design patterns , It is not only widely used in code development , It’s also common in daily life . Like the power adapter on the laptop , It can be used in 110~ 220V Between changes in power , And the laptop works , This is the most direct example of the adapter pattern , At the same time, it is also the embodiment of his thoughts , To put it simply , The adapter pattern is to put a class ( Interface ) Convert to other classes ( Interface ).

Adapter pattern

1、 Definition

Adapter pattern , Also called packaging mode , refer to ** Transform the interface of one class into another interface expected by the client , So that the two classes that could not work together due to interface mismatch can work together .** We can solve the problem of interface incompatibility by adding an adapter class , This adapter class is equivalent to the adapter of the notebook .

Depending on the relationship between the adapter class and the adapter class , Adapter pattern can be divided into object adapter and class adapter , In object adapter mode , Between the adapter and the adapter is relation Relationship ; In the class adapter pattern , Between the adapter and the adapter is Inherit ( Or implementation ) Relationship .

2、UML Class diagram

 Insert picture description here
The adapter pattern contains several roles , They are :

Target( The target character ): This role defines what interface other classes translate to , It can be an abstract class or interface , It can also be a specific class .

Adaptee( The source role ): Who do you want to turn into the target character , This “ who ” That’s the source role , It’s already there 、 A well-functioning class or object .

Adapter( Adapter role ): The core role of the adapter pattern , The responsibility is to transform the source role into the target role by inheritance or class association .

3、 Practical examples

Know what roles and UML After class diagram , We can write the code , For ease of understanding , We use the example of charger in our life to explain the adapter , Now there’s a cell phone to charge , The required rated voltage is 5V, And the voltage of household alternating current is standard 220V, In this case, to charge, an adapter is needed for voltage conversion .

It’s not hard to put the three into the class diagram we drew above , The charger itself is equivalent to Adapter,220V Alternating current is equivalent to Adaptee, Our goal Target yes 5V Direct current .

Target Target interface

public interface Voltage5 {
int output5V();
}

The implementation class of the target interface

public class ConcreteVoltage5 implements Voltage5{
@Override
public int output5V() {
int src = 5;
System.out.println(" Target voltage :" + src + "V");
return src;
}
}

Adaptee class

public class Voltage220 {
// Output 220V The voltage of
public int output220V() {
int src = 220;
System.out.println(" The source voltage is :" + src + "V");
return src;
}
}

Adapter class : complete 220V-5V The transformation of

public class VoltageAdapter extends Voltage220 implements Voltage5 {
@Override
public int output5V() {
// Get the source voltage
int adaptee = super.output220V();
// Start the adaptation operation
System.out.println(" Object adapter works , Start to adapt the voltage ");
int dst = adaptee / 44;
System.out.println(" Output voltage after adaptation :" + dst + "V");
return dst;
}
}

Through the transformation of the adapter class , We can 220V The voltage is converted to what we need 5V The voltage is on , Write a scenario class test :

/**
* Adapter pattern
*/
public class Client {
public static void main(String[] args) {
Voltage5 voltage5 = new ConcreteVoltage5();
voltage5.output5V();
// Create an adapter object
VoltageAdapter2 voltageAdapter = new VoltageAdapter2();
// Switching voltage
voltageAdapter.output5V();
}
}

Results output

 Target voltage :5V
The source voltage is :220V
Object adapter works , Start to adapt the voltage
Output voltage after adaptation :5V

I said before. , There are two adapter modes , What we introduced above is the implementation of class adapter through inheritance , There is also an object adapter , It is implemented by associating the adapter with the adapter , Its general class diagram is shown below :
 Insert picture description here
The code aspect is also relatively simple , Refer to the above example to change the writing method of inheritance to association , The code is not posted , The reader can write for himself .

4、 summary

Let’s summarize the adapter pattern

1) advantage

  • It can realize the decoupling between the target class and the desired role class . The adapter pattern lets two unrelated classes run together , As long as the adapter role can handle them .
  • Increased class transparency . Encapsulate the specific business implementation process in the adapter class , Transparent to client classes , And it improves the reusability of the adapter , The same adapter class can be reused in multiple different systems .
  • Flexibility and scalability are very good . One day , Suddenly I don’t want an adapter , That’s all right. , Just delete the adapter , No other code modify , It’s basically like a flexible component , Use if you want , Uninstall if you don’t want to .

2) shortcoming

  • The class adapter : By way of inheritance , Yes Java For a language that doesn’t support multiple inheritance , Only one adapter class can be adapted at a time , Not very convenient

  • Object adapter : Compared to the class adapter pattern , Some of the ways to replace adapter classes in an adapter are cumbersome . If you must replace one or more methods of the adapter class , You can first make a subclass of the adapter class , Replace the methods of the adapter class , Then, the subclass of the adapter class is regarded as the real adapter for adaptation , The implementation process is more complex .

3) Applicable scenario

  • When it needs to be modified to the online interface , Adapter mode is probably the most appropriate mode .
  • The system expanded , You need to use an existing or new class , But the class does not conform to the interface support of the system , At this point, you can introduce the adapter class to do the transformation .

SpringMVC The underlying adapter pattern

Here we extend the knowledge of adapter pattern , I think I did Java All the developers know SpringMVC, This framework can help us access the front-end requests to the back-end corresponding controller On the way , Then return the result to the back end , Its bottom layer actually uses adapter mode .

SpringMVC The adapter pattern in is mainly used to execute the target Controller Request handling method in . In its underlying processing ,DispatcherServlet As the user ,HandlerAdapter As the expected interface , The specific adapter implementation class is used to adapt the target class ,Controller As a class that needs to be adapted .

Why are you in Spring MVC Using adapter mode ?Spring MVC Medium Controller There are many kinds , Different types of Controller Processing requests in different ways . If you don’t use adapter mode ,DispatcherServlet Get the corresponding type of Controller, So every time you add a type of Controller You need to add one if else Judge instance of, This violates the opening and closing principle of the design mode —— Open to expansion , Turn off for changes .

that SpringMVC How to deal with it ? Let’s take a look at the source code , The first is the adapter interface HandlerAdapter,

public interface HandlerAdapter {
boolean supports(Object var1);
ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;
long getLastModified(HttpServletRequest var1, Object var2);
}

The adapter class of this interface corresponds to Controller, Every custom one Controller You need to define an implementation HandlerAdapter Adapter for . for instance , There is an adapter class HttpRequestHandlerAdapter , This class is the implementation of HandlerAdapter Interface , This is its source :

public class HttpRequestHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
return (handler instanceof HttpRequestHandler);
}
@Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
((HttpRequestHandler) handler).handleRequest(request, response);
return null;
}
@Override
public long getLastModified(HttpServletRequest request, Object handler) {
if (handler instanceof LastModified) {
return ((LastModified) handler).getLastModified(request);
}
return -1L;
}
}

When Spring After the container starts , All defined adapter objects will be stored in one List Collection , When a request comes ,DispatcherServlet Will pass handler Find the corresponding adapter for type , And return the adapter object to the user , Then you can unify the handle Method to call Controller Method for processing requests in .

public class DispatcherServlet extends FrameworkServlet {
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
//.........................
// Find the adapter that matches the current request
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
String requestUri = urlPathHelper.getRequestUri(request);
logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
try {
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
}finally {
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
}
}
// Ergodic set , Find the right matcher
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
for (HandlerAdapter ha : this.handlerAdapters) {
if (logger.isTraceEnabled()) {
logger.trace("Testing handler adapter [" + ha + "]");
}
if (ha.supports(handler)) {
return ha;
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
}

thus , be-all controller All of them will be handed over to HandlerAdapter Handle , There’s no need for a lot of if-else Sentence judgment , At the same time increase controller Type just need to add an adapter , No need to change to Servlet The logic of , Comply with opening and closing principle .

This is the introduction of adapter mode , I hope to point out that .

Reference resources

《 Zen of design pattern 》

https://blog.csdn.net/wwwdc1012/article/details/82780560

发表回复