Contents of article series (continuously updated) :
Chapter 1: Overview, Coupling, UML, Seven Principles, Detailed Analysis and summary (Based on Java)
Chapter two: Several implementations of singleton pattern And its destruction by reflection
【 Design Pattern 】 Chapter 3: A Simple factory, factory method pattern, abstract factory pattern 】
The Builder model is not that difficult
Chapter 5: What is a Prototype Pattern? Shallow fetch shallow copy and deep copy
Article 6: Look at the adapter pattern
[Design Pattern] Chapter 7: Understand the bridge pattern with me
[Design mode] Chapter 8: Drinking soy milk is decorator mode?
[Design Pattern] Chapter 9: Combination pattern to solve the problem of hierarchical structure
[Design mode] Chapter 10: Appearance mode, the joy of driving a small broken car
[Design mode] Chapter 11: Let’s take a look at the yuan model
[Design Mode] Chapter 12: explanation of agent mode in the ticket purchase scene
A quote
Whether students, or office workers, many people get up pressure point out is the norm, stalls shop hurried downstairs to pull a few steamed stuffed bun a cup of soya-bean milk rushed to the subway or bus, small soya-bean milk in this cup, pay attention to it, what kind of soy bean milk, corn there are many different kinds of black sesame soya-bean milk, soy milk, if want to add some ingredients that can be more variety, Like sweet add honey, like eating jujube can also add a few red jujube, unexpectedly possible to meet your needs
In fact, we can see from this example of soybean milk, soybean milk (several kinds, soybeans, grains and so on) itself is an existing product, and adding honey or red dates is to add new functions or beautify existing products, this is what we want to talk about today decorator mode
Further to the technical level, sometimes some component core code is fixed, but without changing the original structure, a certain dynamic extension, also in this way
The following is followed by a soybean milk example of the specific code to introduce its writing, and then on its theory
Ii code Demo
Since it is soybean milk, it belongs to drinks, first define an abstract level of drinks
/** * Abstract beverage class, inherited by soybean milk, etc. */
public abstract class Drink {
private String name; // Drink name
private float price = 0.0 f;
public String getName(a) {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getPrice(a) {
return price;
}
public void setPrice(float price) {
this.price = price;
}
// Calculate the cost
public abstract float calcCost(a);
}
Copy the code
Now that we have abstract drinks, the soya milk class is ready, and don’t forget to implement the abstract method of calculating the cost of drinks in the parent class
/** * Beverage subcategory: soybean milk */
public class SoyaBeanMilk extends Drink {
@Override
public float calcCost(a) {
return super.getPrice(); }}Copy the code
And we have all kinds of soybean milk, such as soybean milk, whole grain soybean milk, black sesame soybean milk
/** * Soybean milk subclass: soybean milk */
public class SoybeansSoyaBeanMilk extends SoyaBeanMilk {
public SoybeansSoyaBeanMilk(a) {
setName("Soya bean milk");
setPrice(3.0 f); }}Copy the code
/** * Soybean milk sub-category: five grain soybean milk */
public class GrainSoyaBeanMilk extends SoyaBeanMilk {
public GrainSoyaBeanMilk(a) {
setName("Whole grain soybean milk");
setPrice(5.0 f); }}Copy the code
/** * Soybean milk subcategory: black sesame soybean milk */
public class BlackSesameSoyaBeanMilk extends SoyaBeanMilk {
public BlackSesameSoyaBeanMilk(a) {
setName("Black sesame soybean milk");
setPrice(6.0 f); }}Copy the code
In fact, we can already get soybean milk in several flavors, but in order to meet the demand, we need to add some different ingredients, such as honey and red dates
First, create a Decorator class, which is collocially our generic name for all ingredients, and there are specific subclasses of ingredients to inherit from it
Note: This is to override the description and cost calculation methods, so inherit Drink and be careful to distinguish which calls are parent and which are your own
/** * decoration */
public class Decorator extends Drink {
private Drink drink;
public Decorator(Drink drink) {
this.drink = drink;
}
@Override
public String getName(a) {
return drink.getName() + "+" + super.getName() + (unit Price) + getPrice() + ")";
}
@Override
public float calcCost(a) {
return super.getPrice() + drink.calcCost(); }}Copy the code
Here are the specific ingredients subcategories
/** * Ingredients subcategory: honey ingredients */
public class Honey extends Decorator{
public Honey(Drink drink) {
super(drink);
setName("Honey");
setPrice(2.0 f); }}Copy the code
/** * Ingredients subclass: jujube ingredients */
public class RedJujube extends Decorator{
public RedJujube(Drink drink) {
super(drink);
setName("Red");
setPrice(3.0 f); }}Copy the code
Test the
public class Test {
public static void main(String[] args) {
Order 1 cup soy milk
Drink drink = new SoybeansSoyaBeanMilk();
System.out.println("Buy." + drink.getName() + "-- Cost:" + drink.calcCost());
Order 1 cup soy milk + 1 part honey
drink = new Honey(drink);
System.out.println("Buy." + drink.getName() + "-- Cost:" + drink.calcCost());
// Order 1 cup soy milk + 1 part honey + 1 part dates
drink = new RedJujube(drink);
System.out.println("Buy." + drink.getName() + "-- Cost:" + drink.calcCost());
// Order 1 cup soy milk + 1 part honey + 2 parts dates
drink = new RedJujube(drink);
System.out.println("Buy." + drink.getName() + "-- Cost:"+ drink.calcCost()); }}Copy the code
Running results:
Buy: Soybean milk — Cost: 3.0 Buy: Soybean milk + honey (unit price 2.0) — Cost: 5.0 Buy: Soybean milk + honey (unit price 2.0) + red dates (unit price 3.0) — Cost: 8.0 Purchase: Soybean milk + honey (unit price 2.0) + red dates (unit price 3.0) + red dates (unit price 3.0) — Cost: 11.0
At this point, it is possible to add ingredients and calculate the total price on top of the basic soymilk category
This is the decorator model, and let’s talk about its theory
The decorator model theory
(I) Definition and understanding
Definition: A decorator pattern is a dynamic way to add responsibilities to an object without changing its structure
As in the soy milk plus ingredients example above, the decoration mode is to add something richer to the existing content
For example, when your system needs new functionality, add some new code to the old code that decorates the core responsibilities or main behaviors of the old class
These new additions, in essence, are meant to meet the needs of certain situations, such as not everyone wants to add honey and other ingredients, for which decorative patterns are a better solution
From above can also be seen in the code, when you need to add decoration on the basis of original content (soybean milk) content (ingredients), only need to put the content of each to decorate in a separate class, then the parcel to decorative objects, when you need to perform add ingredients such a special behavior, can have a choice of decoration, such as adding honey: drink = new Honey(drink); It’s a new drink that’s wrapped in honey.
Also, when you want to add a new kind of soy milk, such as red bean milk, just inherit the parent class of soy milk, and then enjoy the right to add all the ingredients
(2) Advantages and disadvantages
Advantages:
-
This effectively separates the core responsibility of a class from the decorator function, and removes repetitive decorator logic from related classes
-
Decoration is a powerful complement to inheritance, more flexible than inheritance, dynamically extensible, plug and play
-
Decoration classes can be arranged in different order to achieve different effects
-
Observe the open and close principle
Disadvantages:
- Many subclasses are added, making the program more complex
(3) Structure
- Abstract Component roles: Define an abstract interface (class) to dynamically assign blame to these objects
- The ConcreteComponent role: implements an abstract component, that is, a ConcreteComponent
- Decorator role: Inherits an abstract component and contains instances of the concrete component that extend the functionality of the concrete component by subclassing the abstract class above
- ConcreteDecorator: A method for implementing abstract decorators, i.e. concrete ingredients, such as honey, dates