preface

Design patterns permeate every corner of our code. For example, the Observer pattern is implemented by Swing’s ActionsListener class, which was used for the first window application we did when We first started JAVA. Many of the classes in the java. IO package that we use for file manipulation are designed by the decorator pattern. Anyone who has delve deeply into Spring’s source code will be impressed: Spring is the work of some design pattern maniacs.

Design patterns have a very important object-oriented principle: program to the interface, not to the implementation. We have seen some source code in Spring MVC when we debug, troubleshoot or write programs, and most people will find that Spring code is difficult to understand. That’s because most of us think about code in terms of implementation-oriented programming. Of course, it’s very difficult to see the work of a bunch of design pattern maniacs in this way. A good foundation for reading Spring source code, or any other open source code, is familiarity with common design patterns.

Decorator mode

What is decorator pattern? Let’s take a look at Baidu’s interpretation

Dynamically attach responsibility to an object. To extend functionality, decorators provide an alternative to inheritance

Let’s start with the familiar class that implements the decorator pattern in the java.io package. Let’s look at a familiar collection of objects

BufferedInputStream
LinerNumberInputStream
FilterInputStream
FilterInputStream

Decorative Java. IO classes

Our analysis of the java.io class above confirms an important use of decorators: to dynamically attach responsibility to objects.

Why use decorator pattern

We start from the design of a simple drink shop, drink shop with original milk tea, pearl milk tea, green tea, matcha and so on; There are sugar, milk, milk foam and so on. We do a class diagram analysis in our head in the first place.

Classes should be open for extension, but closed for modification

We can see that the beverage store designed by inheritance has great defects: if the price of spices changes, we will change the existing code; Every time a new condiment or beverage is developed, the existing code needs to be changed significantly. Such code maintainability is very poor.

Then we did a redesign using decorator mode

When we combine components with decorator patterns, we add new behaviors. For example, red bean + pearl = red bean pearl milk tea, new tea drinks out, do not need to add a new class.

Code implementation

Beverage Abstractions

Public abstract class Berverage {// public String description; public StringgetDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public abstract int Cost();
}
Copy the code

Abstract flavor class

public abstract class CondimentDecorator  extends  Berverage{
    public abstract String getDescription();
}
Copy the code

The beverage category

public class GreenTea extends Berverage {

    public GreenTea () {
        description = "this is a cup of green tea ";
    }

    public int Cost() {
        return 5;
    }
}
public class MilkTea extends  Berverage {
    public MilkTea() {
        description = "this is a cup of milk tea";
    }
    public int Cost() {
        return 6;
    }
}

public class PearlsMilkTea extends Berverage {
    public PearlsMilkTea() {
        description = "this is a cup of pearls milk tea ";
    }
    public int Cost() {
        return2; }}Copy the code

Condiments class

Public class Milk extends CondimentDecorator {// Milk Berverage Berverage; public Milk( Berverage berverage) { this.berverage = berverage; } public StringgetDescription() {
        return berverage.getDescription()+"+milk";
    }

    public int Cost() {
        returnberverage.Cost()+3; }}Copy the code

The test code

Public class Application {public static void main(String[] args) {// berverage1 = new PearlsMilkTea(); System.out.println(berverage1.getDescription() +" cost = "+ berverage1.Cost()); // GreenTea with milk Berverage Berverage = new GreenTea(); berverage = new Milk(berverage); System.out.println(berverage.getDescription()+"cost = "+berverage.Cost()); }}Copy the code

The test results

Non-alcoholic drinks

Decorator pattern: Dynamically attaches responsibility to an object. To extend functionality, decorators provide an alternative to inheritance

Two important principles of object-oriented design are covered in this section

  • Program to the interface, not to the implementation
  • Classes should be open for extension, but closed for modification

The last

In the company of three, there must be my teacher. At the same time to share dry goods to everyone, talent and learning shallow also hope that everyone to be made right. Also welcome to pay attention to my nugget or brief book, named firewood yards