1. Basic introduction
- Dynamically attach new functions to objects. In terms of function extension, it is more flexible than inheritance, reflecting the opening and closing principle
2. Principle
1. Schematic diagram
2. Analysis
The decorator mode is like packing a express delivery. The items to be sent are the main body, that is, the decorated class, and the packing is the decoration class, which packs the main body
- Component: decorated body
- ConcreteComponent: the specific body to be decorated
- Decorator: decorator
- A buffer layer can also be designed between Component and ConcreteComponent to create a common class to abstract the common characteristics of each ConcreteComponent
3. Cases
Decorator pattern implementation class diagram
Role analysis
- Drink is the abstract class of decorator, Component
- ShortBlack is the single coffee
- Decorator is a decorator class that contains a decorated object (Drink obj)
- The cost method of decorator is used to perform a cost superposition calculation and recursively calculate the price
code implementation
Drink class
public abstract class Drink { public String des; private float price = 0.0f; public String getDes() { return des; } public void setDes(String des) { this.des = des; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } //Abstract method of calculating cost //Subclass to implement public abstract float cost(); }
Take the common part of single coffee
public class Coffee extends Drink{ @Override public float cost() { // TODO Auto-generated method stub return getPrice(); } }
Implementation of single category
public class LongBlack extends Coffee{ public LongBlack() { setDes("LongBlack"); setPrice(18.0f); } }
Decorator
public class Decorator extends Drink{ private Drink obj; public Decorator(Drink obj) { super(); this.obj = obj; } @Override public float cost() { // TODO Auto-generated method stub return obj.cost() + super.getPrice(); } @Override public String getDes() { // TODO Auto-generated method stub return super.getDes()+""+getPrice()+"&&"+obj.getDes(); } }
Specific condiments: coffee with a single combination
//Specific Chocolate, this is condiment public class Chocolate extends Decorator{ public Chocolate(Drink obj) { super(obj); // TODO Auto-generated constructor stub setDes("Chocolates"); setPrice(3.0f); //Price of condiments } }
4.IO source code analysis
Structure chart
analysis
InputStream is an abstract class, which has many subclasses (concrete subjects, such as FileInputStream), belonging to the principal role in decorator pattern, in which many abstract methods are defined to be implemented by subclasses
public abstract class InputStream implements Closeable {
FileInputStream, a subclass of InputStream, serves as the concrete principal class
public class FileInputStream extends InputStream {
FilterInputStream decorator class, inheriting InputStream and combining an InputStream, conforms to the role of decorator mentioned above
public class FilterInputStream extends InputStream { /** * The input stream to be filtered. */ protected volatile InputStream in;
The subclass of FilterInputStream has combined and assigned values to InputStream, which serves as the condiment of the above example
public class DataInputStream extends FilterInputStream implements DataInput { /** * Creates a DataInputStream that uses the specified * underlying InputStream. * * @param in the specified input stream */ public DataInputStream(InputStream in) { super(in); }
The pattern described above is the same when we apply it
//Create a decoration class that contains the main InputStream, pass the main item to the constructor, and obtain a wrapped FileInputStream object, which is already a DataInputStream object DataInputStream dataInputStream = new DataInputStream(new FileInputStream(file));