definition
Decorator Pattern is to dynamically attach responsibilities to objects. To extend functionality, decorators offer a more flexible alternative than inheritance—— HEAD First design pattern
Main role
Abstract decorated Component: the most primitive object that needs to be decorated. Such as the coverage class (super class) in the example.
Concrete decorated ConretetComponent: a concrete Component that implements the abstract methods in the Component abstract class through inheritance. It's the one to decorate. Like the single coffee in the example.
Abstract Decorator: an abstract class. In its properties, there must be a private variable pointing to the Component abstract Component. This is an example of all kinds of milk and other spices.
Concrete decorator
give an example
It is derived from the Head FIRST design pattern to realize the coffee shop business.
Coffee types: Espresso, ShortBlack (concentrated), LongBlack, Decaf (sugar free)
Spices include Milk, Soy and Chocolate, that is, add Milk, Chocolate and so on to the basic varieties.
First, define the Beverage class, which is the abstract class of all drinks and the class to be decorated:
public abstract class Beverage { public String description="Unknown Beverage"; //This description extends to specific items or condiments public String getDescription() { return description; } public abstract double cost(); //This is abstract because the price can be returned directly in a single variety
So is the seasoning class:
public class CondimentDecorator extends Beverage { //All condiment decorators must re implement the getDescription() method to get the overall description of the selected beverage recursively public abstract String getDescription(); }
With these two base classes, we need to implement some drinks:
Espresso:
public class Espresso extends Beverage { public Espresso() { description = "Espresso"; } //Return Espresso price @Override public BigDecimal cost() { return new BigDecimal("1.99"); } }
Deep roasted coffee:
public class DarkRoast extends Beverage { public DarkRoast() { description = "DarkRoast"; } //Returns the price of dark toast @Override public BigDecimal cost() { return new BigDecimal("0.89"); } }
Next, implement some spices
Soybean milk seasoning:
public class Soy extends CondimentDecorator { //Use an instance variable to record the beverage, that is, the decorator Beverage beverage; //Pass in the drink as a parameter and record it in the variable public Soy(Beverage beverage) { this.beverage = beverage; } //Add Soy description on the basis of the original beverage (the original beverage is added with Soy sauce and decorated with Soy sauce) @Override public String getDescription() { return beverage.getDescription() + ",Soy"; } //Add the price of Soy sauce to the original beverage (the original beverage is decorated with Soy sauce) @Override public BigDecimal cost() { return new BigDecimal("0.3").add(beverage.cost()); } }
Similarly, define a milk bubble seasoning:
public class Whip extends CondimentDecorator { Beverage beverage; public Whip(Beverage beverage) { this.beverage = beverage; } public String getDescription() { return beverage.getDescription() + ",Whip"; } public BigDecimal cost() { return new BigDecimal("0.42").add(beverage.cost()); } }
This defines two basic drinks and two spices. In the actual order, a cup of deep roasted coffee beverage with soybean milk and milk foam is required:
public class StarbuzzCoffee { public static void main(String[] args) { Beverage beverage = new DarkRoast(); beverage = new Soy(beverage); beverage = new Whip(beverage); System.out.println("Description: " + beverage.getDescription() + " $" + beverage.cost()); } }
The operation result is:
Description: darkroast,Soy,Whip $1.61
Usage scenario
When class inheritance will cause class explosion and is not conducive to later maintenance, decorator mode can be adopted. For example, milk tea can be seasoned at will.
When you need to dynamically add functionality to an object and can dynamically undo it, you can use decorator mode.
Advantages and disadvantages
advantage
- Decorated classes and decorated classes can develop independently without coupling each other. It effectively separates the core responsibility of the class from the decorating function
- Decoration pattern can dynamically extend the function of an implementation class
- It embodies the opening and closing principle: classes should be open to extensions and closed to modifications
shortcoming
Multi layer decoration is more complex. For example, we now have many layers of decoration. If something goes wrong, check it layer by layer
Decorator Pattern instance in Java -- Java IO
Drawing source: Design mode (III) -- decorator mode
InputStream is an abstract component that needs to be decorated; FileInputStream, StringBufferInputStream and ByteArrayStream are specific components wrapped by decorators.
FileInputStream and other three are some subjects. FilterInputStream is an abstract decorator, and the following are some specific decorators.
Java IO example
To convert all input to lowercase:
//Extend FilterInputStream public class LowerCaseInputStream extends FilterInputStream{ protected LowerCaseInputStream(InputStream in) { super(in); } //Similar to the cost method, it implements two read methods, one for byte array and one for byte array public int read() throws IOException { int c = super.read();//Call the topic object of super(in) above return c == -1 ? c : Character.toLowerCase((char)(c)); } public int read(byte[] b,int offset,int len) throws IOException//For byte array { int result = super.read(b,offset,len); for(int i = offset;i < offset + result; i++) { b[i] = (byte)Character.toUpperCase((char)(b[i])); } return result; } }
Then use this decorator mode:
public class InputTest { public static void main(String[] args) { int c; try { InputStream in = new LowerCaseInputStream(new BufferedInputStream(new FileInputStream("test.txt"))); while((c = in.read()) >= 0) { System.out.print((char)c); } in.close(); } catch (IOException e) { e.printStackTrace(); } } }
reference resources
Head FIRST design pattern
Design mode (III) -- decorator mode
Decorator mode of design mode
On design mode -- decoration mode
Decorator mode of design mode