An overview,

  • Decorator pattern: Dynamically appends new functionality to objects. It is more flexible than inheritance in extending object functionality, and decorator pattern also embodies the open closed principle (OCP)
  • Decorator pattern is like packaging a package, the body is Component; The wrapper is a Decorator; ConcreteComponent is a concrete subject
  • Feel this method, much like the proxy mode, but this is a static operation, relatively large limitations

Decorator mode to solve the problem of coffee orders

  • Set up an abstract base classDrink, including the price of the itempriceAnd the descriptiondescProperties. Set up an abstract method,cost()
public abstract class Drink {
  private String desc;
  private double price;
  public Drink(a) {}public Drink(String desc, double price) {
    this.desc = desc;
    this.price = price;
  }
  public String getDesc(a) {
    return desc;
  }
  public void setDesc(String desc) {
    this.desc = desc;
  }
  public double getPrice(a) {
    return price;
  }
  public void setPrice(double price) {
    this.price = price;
  }
  public abstract double cost(a);
  public abstract String getDescription(a);
}
Copy the code
  • Abstract base classCoffeeinheritanceDrink.cost()Represents the current price of the drink, which is of the current classpriceAttributes, that is, adding nothing;getDesccription()To describe the combination and price of the whole beverage, only single beverage and price are available at present
public abstract class Coffee extends Drink {
  public Coffee(a) {}public Coffee(String desc, double price) {
    super(desc, price);
  }
  @Override
  public double cost(a) {
    return super.getPrice();
  }
  @Override
  public String getDescription(a) {
    return super.getDesc() + "" + super.getPrice() + ""; }}Copy the code
  • Concrete coffee implementation class, set the price and description of the item in the constructor
public class Decaf extends Coffee {
  public Decaf(a) {
    super("Decaf".6.0); }}Copy the code
  • Abstract base classDecorator, and through inheritance and combinationDrinkAn association occurs. That is, it’s a cup of coffee in itself, and it has a property of coffee before the ingredient is added.cost()Is equal to the current price of the itempriceAdd attributeDrinkthecost().getDesccription()In the same way
public abstract class Decorator extends Drink {
  Drink drink;
  public Decorator(Drink drink) {
    this.drink = drink;
  }
  public Decorator(String desc, double price, Drink drink) {
    super(desc, price);
    this.drink = drink;
  }
  @Override
  public double cost(a) {
    return this.getPrice() + drink.cost();
  }
  @Override
  public String getDescription(a) {
    return drink.getDescription() + super.getDesc() + "" + super.getPrice() + ""; }}Copy the code
  • For the specific feeding implementation class, set the price and description of the item in the constructor, and accept what needs to be packagedDrink()
public class Milk extends Decorator {
  public Milk(Drink drink) {
    super("Milk".2.0, drink); }}Copy the code
  • call
public class Client {
  public static void main(String[] args) {
    Drink shortBlack = new ShortBlack();
    System.out.println(shortBlack.getDescription());
    System.out.println(shortBlack.cost());

    Chocolate chocolate = new Chocolate(shortBlack); // Wrap one layer
    System.out.println(chocolate.getDescription());
    System.out.println(chocolate.cost());

    Milk milk = new Milk(chocolate);  // Wrap another layer
    System.out.println(milk.getDescription());
    System.out.println(milk.cost());

    Chocolate chocolate1 = new Chocolate(milk); // Wrap another layerSystem.out.println(chocolate1.getDescription()); System.out.println(chocolate1.cost()); }}Copy the code