I'm < font color = #2941c0 > "kangarooking" < / font >, not my brother's brother. An Internet worm "gua" cow will climb up step by step with you. One day there will be a day for us. Pay attention to me and make a little progress every day ❗ ❗ ❗
preface
The experience of learning design mode mentioned in the article on responsibility chain mode in the previous issue was originally intended to be written to tiezi in this issue, but after thinking about it, I feel that the time is not ripe. I'm going to tell you in my concluding article after the "easy to understand design patterns" series.
hum about
I don't know if you have the feeling that design patterns seem to be mostly used in the framework, and design patterns have not been used in your own business code. In fact, many business scenarios can be solved by using design patterns, but they may not be used because the person in charge has a relatively simple understanding of design patterns, or because the project is in a hurry. So today's article is powerful 0.0. After reading it, you can directly introduce the decorator mode into your own project, so that the leaders will look at you with new eyes, promote and raise salary, and win baifumei. It's a little pleasant to think about it 😍, Take off take off~ ✈️
concept
The definition of Decorator Pattern: refers to the pattern that dynamically adds some responsibilities (i.e. adds its additional functions) to the object without changing the existing object structure. It belongs to object structure pattern.
advantage:
- Decorator is a powerful supplement to inheritance, which is more flexible than inheritance. It can dynamically extend the function of an object without changing the original object, plug and play
- Different effects can be achieved by using different decorative classes and the arrangement and combination of these decorative classes
- The decorator mode fully complies with the opening and closing principle
Disadvantages:
- Decorator pattern will add many subclasses, and overuse will increase the complexity of the program.
Why not use inheritance?
Usually, the function of extending a class will be implemented by inheritance. However, inheritance has static characteristics, high coupling, and subclasses will expand with the increase of extended functions.
The goal of decorator mode
Use the combination relationship to create a wrapper object (i.e. decoration object) to wrap the real object, and provide additional functions for the real object on the premise of keeping the class structure of the real object unchanged.
Decorator mode usage scenario
- When you need to add additional responsibilities to an existing class, but you can't expand it by generating subclasses. For example, if the class is hidden, or the class is the ultimate class, or inheritance will produce a large number of subclasses.
- When it is necessary to arrange and combine a set of existing basic functions to produce many functions, it is difficult to realize the inheritance relationship, but it is easy to realize the decorator mode.
- When the functional requirements of the object can be added dynamically or revoked dynamically.
Define roles
Target object: the original object to be decorated;
Decorator Abstract: an abstract decorator;
Concrete decorator: the concrete implementation of the abstract decorator.
Code example
Business scenario: there are many preferential methods for company orders, such as coupons, vip discounts, points activities, red envelopes and so on At this time, we can consider using the decorator mode to decorate the original order object. Through decoration, the ordinary order can become an order containing multiple / single preferential activities< Br / > code address: https://gitee.com/kangarookin... < br / > note: this example is just a simple help to understand that the code implementation of the design pattern is far from the actual project. For the order discount realized by the actual project, please refer to: https://blog.csdn.net/ceoaxv5...
Order class
@Data @AllArgsConstructor @NoArgsConstructor public class Order { private Double price; private Integer orderId; private String orderNo; private Double pay; private List<Integer> promotionTypeList; }
The enumeration class of the activity, which is used to record the activity type
/** * Activity enumeration */ public enum PromotionType { COUPON(1), VIP(2); private int type; PromotionType(final int type){ this.type = type; } public int getType() { return type; } public void setType(int type) { this.type = type; } }
Decorator interface of decoration order
/** * Order decorator interface */ public interface OrderDecorator { //Abstract decoration method Order decorator(Order order); }
Order decorator implementation class -- coupon order decorator
/** * Coupon decorator */ public class CouponOrderDecorator implements OrderDecorator { @Override public Order decorator(Order order) { System.out.println("Coupon minus 3 yuan"); order.setPay(order.getPrice() - 3); order.setPrice(order.getPrice() - 3); System.out.println("Paid in:" + order.getPay()); return order; } }
Order decorator implementation class -- VIP order decorator
/** * vip Decorator */ public class VipOrderDecorator implements OrderDecorator { @Override public Order decorator(Order order) { System.out.println("vip Minus 1 yuan"); order.setPay(order.getPrice() - 1); order.setPrice(order.getPrice() - 1); System.out.println("Paid in:" + order.getPay()); return order; } }
Let's see how to use it
public class DecoratorClient { public static void main(String[] args) { //Create an original order Order order = new Order(10d, 1, "0001", 10d, null); //Create decorator subclass object OrderDecorator vipOrderDecorator = new VipOrderDecorator(); OrderDecorator couponOrderDecorator = new CouponOrderDecorator(); //Pack the original order object with vip and coupons to make it have the benefits of vip and coupons. //In some cases (implemented according to specific requirements), different results can be obtained according to the order of packaging. Order vipCouponOrder = couponOrderDecorator.decorator(vipOrderDecorator.decorator(order)); } }
The use of decorator pattern in open source code
java. Application in io
The most famous application of decorator pattern in Java language is the design of Java I/O standard library. For example, the subclass FilterInputStream of InputStream, the subclass FilterOutputStream of OutputStream, the subclass BufferedReader and FilterReader of Reader, and the subclass BufferedWriter, FilterWriter and PrintWriter of Writer are abstract decoration classes.
Let's take a look at an example. BufferedReader implements the decorator by inheriting the Reader class and defining the Reader class as its own member variable. The Reader here is the abstract of the decorator and the target object. BufferedReader is the concrete decorator and the target object.
FilterReader is implemented in the same way as BufferedReader
Why doesn't BufferedReader use the implementation of the above example code?
In fact, this is an old saying - design pattern is an idea, and there are many ways to realize it. There is no decorator() method similar to that in the sample code inside the BufferedReader class, so it introduces the target object by defining the target object as a member variable (rather than defining a formal parameter of the target object), so as to decorate the functions of other Reader implementation classes to itself.
Here is just a brief description of the usage of this implementation decorator. You can have a look at the specific internal source code. The internal of the method finally calls in XXX method.
public static void main(String[] args) throws IOException { Reader file = new FileReader("xxx route"); //FileReader is used for decoration in FilterReader FilterReader filterReader = new PushbackReader(file); //Use FilterReader for decoration in BufferedReader Reader bufferedReader = new BufferedReader(filterReader); //Finally, call the read and close methods of BufferedReader //The function of filerreader is obtained bufferedReader.read(); bufferedReader.close(); }
Application of shenyu in gateway
shenyu context decorator interface is mainly used to assemble different context information according to different access types.
shenyu's grpc context decorator implements the class in the same way as the instance code. A decorator() method passes in the target object ShenyuContext as a formal parameter, and then decorates ShenyuContext with grpc type in this method.
shenyu is also a nice open source gateway framework. It is a new open source work of Chinese people, which has high learning value and practicability. I introduced the gateway in the architecture group of my old owner at that time, which was maintained and opened by our architecture group. Therefore, I am familiar with the internal implementation of this gateway framework, and I often use it as an example.
github address: https://github.com/apache/inc... < br / > official document address: https://shenyu.apache.org/
summary
Or is the old design pattern an idea? What we need is to master and understand the idea, and transform it into the implementation in the code and apply it to the actual work. Brothers can usually pull the source code of several open source frameworks to the local place. When they are free, they can see how others write the code. For example, in the decorator mode, they can search the decorator globally to find the relevant code.
WeChat official account <font color=#2941c0> "kangaroo's Inn" </font>, your three Lian, is my feed ~ ~. give the thumbs-up 👍 follow ❤ Share 👥