当前位置:网站首页>Necessary decorator mode for 3 years' work

Necessary decorator mode for 3 years' work

2022-06-26 16:57:00 Tianweichang

Focus on “Java Back end technology stack ”

reply “000” Access to a lot of e-books

Hello everyone , I'm Lao Tian , Starting today , This official account is given to you every week Give benefits , What do you give ? It must be a technical book , There are not so many fancy things , The way of participation is shown at the end of the article .

All right. , Enter our theme , Today I'd like to share with you Decorator mode . With the right life story , And design patterns in real project scenarios , Finally, I want to summarize this design pattern with one sentence .

Design pattern series , We've shared :

3 Necessary for annual work Facade mode

3 Necessary for annual work The singleton pattern

3 Necessary for annual work   The strategy pattern

3 Necessary for annual work Template method pattern

The story

The old saying goes well : People depend on clothes and horses on saddles . Let's get familiar with the background of this sentence :

A man depends on his clothes and a horse on his saddle , The joy of dogs running with bells comes from Shen Zijin 《 The story of Wanghu Pavilion 》 The tenth :“ Even so , Buddha relies on gold. , Clothes are for men. , It's also important to dress up .”《 Wake up to the world 》 Volume one ‧ Two county magistrates compete to marry an orphan girl :” As the saying goes :’ Buddha is gold , People are clothes , There are many shallow eyes in the world , Only skin , There's no bone .’” As the saying goes, men depend on clothes and horses on saddles .

This classic story , It reminds me of a design pattern : Decorator mode .

What is decorator mode ? Please listen to Lao Tian's words .

An overview of decorator patterns

Decorator mode (Decorator Pattern) It's also called wrapper mode (Wrapper Pattern), On the basis of not changing the original object , Dynamically add some additional responsibilities to an object . In terms of adding functionality , Decorator mode is more flexible than subclassing , It belongs to structural design mode .

english :

Attach additional responsibilities to an object dynamicallykeeping the same interface.Decorators provide a flexible alternativeto subclassing for extending functionality.

The decorator pattern provides a more flexible alternative than inheritance ( Extend the function of the original object ) Attach functions to objects . therefore , The core of decorator mode is function extension . Using the decorator pattern, you can extend the functions of a class transparently and dynamically .

Cases in life

A blank room , Before the decoration , It looks very ugly , But just a little renovation , That would be much more beautiful , And can take a bath 、 sleep 、 Cooking, etc , But the essence is the house .

A car , Originally, it was a vehicle for people to walk , But Mary is , Configuration upgrade , And then it became a luxury car , But in essence, it's still a car to go .

A girl , It used to be very ordinary , Looks average , But after a bit of make-up , Put on some nice clothes , Then she became the goddess in many people's hearts .

All in all , After a little decoration , It's just different , Features enhanced .

Decorator pattern common code implementation

Let's use code to implement a , Programmers like to start with demo, And then slowly study .

// Abstract components 
public abstract class Component {
    public abstract void operation();
}
// Specific components 
public class ConcreteComponent extends Component {
    @Override
    public void operation() {
        System.out.println("ConcreteComponent operation");
    }
}
// Decorator abstraction 
public abstract class Decorator extends Component {

    protected Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public void operation() {
        component.operation();
    }
}
// Specific ornaments 
public class ConcreteDecorator extends Decorator {
    public ConcreteDecorator(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        System.out.println(" Do something before you start ");
        super.operation();
        System.out.println(" Do something after it's over ");
    }
}
// test 
public class Client {
    public static void main(String[] args) {
        Component component = new ConcreteDecorator(new ConcreteComponent());
        component.operation();
    }
}

Running results :

 Do something before you start 
ConcreteComponent operation
 Do something after it's over 

The above is the common code implementation of decorator pattern , Let's analyze .

Decorator mode UML chart


from UML You can see on the way , The role

Characters in decorator mode

  • Abstract components (Component): It can be an interface or an abstract class , Act as the original object of the decorated class , Specifies the behavior of the decorated object .

  • Specific components (ConcreteComponent): Realization / Inherit Component A specific object of , That is, the object to be decorated .

  • Abstract decorator (Decorator): General decoration ConcreteComponent The decorator , There must be an attribute inside it pointing to Component; Its implementation is generally an abstract class , The main purpose is to let its subclass pass in a Component, It's mandatory universal behavior . If the decoration logic in the system is single , You don't need to implement many decorators , This class can be omitted directly , And directly implement a specific decorator .

  • Specific ornaments (ConcreteDecorator):Decorator Implementation class of , Theoretically , Every ConcreteDecorator It's all expanded Component A function of an object .

Summary

The role assignment of decorator pattern is in accordance with Richter's substitution principle of design pattern 、 The principle of Dependence Inversion , So it has strong expansibility , Finally, the open close principle is satisfied .

The implementation principle of decorator mode is , Let the decorator implement with the decorated class ( for example ConcreteComponent) Same interface ( for example Component), Make the decorator consistent with the extended class type , And pass in the interface object in the constructor , Then add new functionality to the existing functionality of the wrapped class object that implements this interface . Because the decorator and the packaged class belong to the same type ( Are all Component), And the parameter of the constructor is its implementation interface class (Component), Therefore, decorator pattern has nested extension function , In this way, the decorator pattern can be used to extend the functions of the underlying packaged classes layer by layer .

actual combat

In actual development , There will be calls between systems , If we have a payment function now , Now everything is OK , however At this time, we need to check the request parameters before payment and the corresponding parameters after payment . To carry out a unified treatment , The original function remains unchanged , It's just an extension of the original function ( enhance ).

The old function code is as follows :

/**
 * @author  Mr. Tian 
 * @date 2021-06-02
 *
 *  Welcome to the official account :java Back end technology stack 
 */
public interface IOrderPayService {
    String payment(Long orderId, BigDecimal amount);
}
public class OrderPayServiceImpl implements IOrderPayService {

    @Override
    public String payment(Long orderId, BigDecimal amount) {
        // Call balance first to check whether it is enough 
        System.out.println(" Initiate payment , The order number :" + orderId + ",  Pay the amount :" + amount.toString());
        // Call the payment system 
        String result = " Order id=" + orderId + " Pay to complete ";
        System.out.println(" Payment result :" + result);
        return result;
    }
}
public class OrderClient {
    public static void main(String[] args) {
        IOrderPayService orderPayService = new OrderPayServiceImpl();
        orderPayService.payment(10001L,new BigDecimal("5000"));
    }
}

Operation output :

 Initiate payment , The order number :10001,  Pay the amount :5000
 Payment result : Order id=10001 Pay to complete 

The new demand , These request parameters and corresponding results need to be collected and processed separately , At this time, in order not to affect the original function , So we can enhance it .

/**
 * @author  Mr. Tian 
 * @date 2021-06-02
 *
 *  Welcome to the official account :java Back end technology stack 
 */
public class OrderPayDecorator implements IOrderPayService {

    private IOrderPayService orderPayService;

    public OrderPayDecorator(IOrderPayService orderPayService) {
        this.orderPayService = orderPayService;
    }

    @Override
    public String payment(Long orderId, BigDecimal amount) {
        System.out.println(" Send this order information ( Initiate payment )" + " Order id=" + orderId + " Pay the amount =" + amount.toString() + " 【 Send to MQ】");
        String result = orderPayService.payment(orderId, amount);
        System.out.println(" Send the order payment result information " + result + " 【 Send to MQ】");
        return result;
    }
}
public class OrderClient {
    public static void main(String[] args) {
        IOrderPayService orderPayService =new OrderPayDecorator(new OrderPayServiceImpl());
        orderPayService.payment(10001L,new BigDecimal("5000"));
    }
}

Operation output :

 Send this order information ( Initiate payment ) Order id=10001 Pay the amount =5000 【 Send to MQ】
 Initiate payment , The order number :10001,  Pay the amount :5000
 Payment result : Order id=10001 Pay to complete 
 Send order payment result information to order id=10001 Pay to complete  【 Send to MQ】

The whole process , Have you noticed that , We didn't move the original code , It's just an enhancement .

Decorator mode will not be used in new projects , Usually used in old projects , Because the existing functions remain unchanged , Just a few enhancements .

How the gods use it

Decorator design pattern in JDK Source code 、Spring Source code and Mybatis Source code has .

JDK Source code

The classic application of decorator mode is JDK Medium java.io It's a bag ,InputStream、OuputStream、Reader、Writer And their subclasses .

With InputStream For example

  • FileInputStream yes InputStream Subclasses of , Used to read file byte stream

  • BufferedInputStream yes InputStream Subclasses of subclasses of , Cacheable byte stream

  • DataInputStream It's also  InputStream Subclasses of subclasses of , Direct reading Java Basic type of byte stream

UML chart


DataInputStream The constructor's input parameter is its own parent class (InputStream).

If you want to provide a file that can be read + Cacheable byte stream , Use inheritance , You need to derive FileBufferedInputStream;

If you want to provide a file that can be read + Read the basic type of byte stream directly , Use inheritance , You need to derive FileDataInputStream.

Byte stream enhancements also include support for pipelines pipe、 Byte array bytearray、 Byte object object、 Conversion of byte stream and character stream Equal dimension , If by inheritance , There will be so many levels and types of that kind of explosion .

To solve the problem , Here we use the decorator mode .

Spring Source code

stay Spring in , We can try to understand TransactionAwareCacheDecorator class , This class is mainly used for transaction caching , The code is as follows .

public class TransactionAwareCacheDecorator implements Cache {
    private final Cache targetCache;
    // The input parameter type of construction method is its own parent class ( Interface type )
    public TransactionAwareCacheDecorator(Cache targetCache) {
        Assert.notNull(targetCache, "Target Cache must not be null");
        this.targetCache = targetCache;
    }

    public Cache getTargetCache() {
        return this.targetCache;
    }
    //...
}

TransactionAwareCacheDecorator That's right Cache A package of , therefore , The decorator mode is also used here .

Mybatis Source code

MyBatis About China Cache and CachingExecutor Interface implementation classes also use decorator design patterns .Executor yes MyBatis actuator , yes MyBatis The core of scheduling , be responsible for SQL Statement generation and query cache maintenance ;CachingExecutor It's a Executor The decorator , Give me a Executor Added the function of cache . This can be seen as right Executor An enhancement of class , So it is appropriate to use decorator mode .

stay CachingExecutor in

public class CachingExecutor implements Executor {
  // Holding component objects 
  private Executor delegate;
  private TransactionalCacheManager tcm = new TransactionalCacheManager();
    // Construction method , Pass in the component object 
  public CachingExecutor(Executor delegate) {
    this.delegate = delegate;
    delegate.setExecutorWrapper(this);
  }
  @Override
  public int update(MappedStatement ms, Object parameterObject) throws SQLException {
      // Forward request to component object , You can perform additional actions before and after forwarding 
    flushCacheIfRequired(ms);
    return delegate.update(ms, parameterObject);
  }
  //...
 }

summary

After watching decorator mode , Do you feel , Decorator mode is very similar to proxy mode , Let's make a comparison .

1. Decorator pattern can be understood as a special proxy pattern .

2. Decorator mode emphasizes its own function expansion , Transparent extension ( That is, users can enhance whatever functions they want to enhance ), Dynamic customizable extensions .

3. Agent mode emphasizes the control of agent process .

advantage

  • Ornaments are a powerful complement to inheritance , More flexible than inheritance , Without changing the original object , Dynamically extend functions to an object , Plug and play .

  • Through the use of different decoration classes and the arrangement and combination of these decoration classes , Different effects can be achieved .

  • Decorator mode fully follows the opening and closing principle .

shortcoming

  • There will be more code 、 More classes , Increase the complexity of the program .

  • Dynamic decoration is more complicated in multi-layer decoration .

Okay , That's the end of today's sharing , I hope you can master the decorator mode thoroughly , If there is any doubt , Or technical discussions , Welcome to wechat , To discuss .

Last , One sentence summary decorator mode :

His big uncle, second uncle, third uncle, little uncle , It's all his uncle

Welfare password

Enter the following official account , Send a reply 20210602, You can get the way to participate .

Previous recommendation

121 Distributed interview questions and answers ,25K Proper

Enter Baidu !

Don't be incredulous ,98% All programmers are like this

Will know RabbitMQ Interview questions 33 Avenue ( Answer attached )

use 21 Pictures , hold Git The working principle is completely clear

10 minute ! Handle the context of distributed transactions

原网站

版权声明
本文为[Tianweichang]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202170500469028.html