设计模式-装饰者模式

本文最后更新于:6 个月前

什么是装饰者模式

装饰者模式允许向一个现有的对象添加新的功能,同时又不改变其结构。

动态地给一个对象添加一些额外的职责。就增加功能来说,装饰者模式相比生成子类更为灵活。

结构

  • 抽象构建角色:定义抽象接口以规范准备接受附加责任的对象。
  • 具体构建角色:实现抽象构建,通过装饰角色为其添加职责。
  • 抽象装饰角色:继承或实现抽象构建,并包含具体构建的实例,可以通过子类扩展具体构建的功能。
  • 具体装饰角色:实现抽象装饰的相关方法,并给具体 构建对象添加附加的责任。

demo

点此处下载源码

两个demo分别来自黑马和尚硅谷,个人认为黑马的这个案例讲解得更加清晰。

快餐店

image-20210512134408717

(图片有小错误,菱形的位置有错)

package decorator.demo_fastFood;

/**
 * @author QiuQian
 * 抽象构建角色
 */
public abstract class FastFood {
    private double price;
    private String desc;

    public FastFood() {
    }

    public FastFood(double price, String desc) {
        this.price = price;
        this.desc = desc;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public abstract double cost();
}


package decorator.demo_fastFood;

/**
 * @author QiuQian
 * 具体构建角色
 */
public class FriedNoodle  extends FastFood{

    public FriedNoodle() {
        super(15, "炒面");
    }

    @Override
    public double cost() {
        return getPrice();
    }
}


package decorator.demo_fastFood;

/**
 * @author QiuQian
 * 具体构建角色
 */
public class FriedRice extends FastFood{
    public FriedRice() {
        super(10, "炒饭");
    }

    @Override
    public double cost() {
        return getPrice();
    }
}


package decorator.demo_fastFood;

/**
 * @author QiuQian
 * 抽象装饰角色
 * 具体加什么配料并不明确,所以定义为抽象类
 */
public abstract class Garnish extends FastFood {
    private FastFood fastFood;

    public FastFood getFastFood() {
        return fastFood;
    }

    public void setFastFood(FastFood fastFood) {
        this.fastFood = fastFood;
    }

    public Garnish(FastFood fastFood, double price, String desc) {
        super(price, desc);
        this.fastFood = fastFood;
    }
}


package decorator.demo_fastFood;

/**
 * @author QiuQian
 * 具体装饰角色
 */
public class Egg extends Garnish {
    public Egg(FastFood fastFood) {
        super(fastFood, 2, "鸡蛋");
    }

    @Override
    public double cost() {
        // 鸡蛋的价格 + 快餐的价格
        return getPrice() + getFastFood().cost();
    }

    @Override
    public String getDesc() {
        // 鸡蛋的描述 + 快餐的描述
        return super.getDesc() + " " + getFastFood().getDesc();
    }
}


package decorator.demo_fastFood;

/**
 * @author QiuQian
 * 具体装饰者角色
 */
public class Bacon extends Garnish {
    public Bacon(FastFood fastFood) {
        super(fastFood, 5, "培根");
    }

    @Override
    public double cost() {
        return getPrice() + getFastFood().cost();
    }

    @Override
    public String getDesc() {
        return super.getDesc() + getFastFood().getDesc();
    }
}


package decorator.demo_fastFood;

/**
 * @author QiuQian
 */
public class Client {
    public static void main(String[] args) {
        FastFood friedNoodle = new FriedNoodle();
        System.out.println(friedNoodle.getDesc() + " " + friedNoodle.cost() + "元");
        friedNoodle = new Egg(friedNoodle);
        System.out.println(friedNoodle.getDesc() + " " + friedNoodle.cost() + "元");

        System.out.println("===================");

        FastFood fireRice = new FriedRice();
        System.out.println(fireRice.getDesc() + " " + fireRice.cost() + "元");
        fireRice = new Bacon(fireRice);
        System.out.println(fireRice.getDesc() + " " + fireRice.cost() + "元");

    }
}

运行结果

image-20210512140429325

咖啡

package decorator.demo_coffee;

/**
 * @author QiuQian
 * 抽象构建角色
 */
public abstract class Drink {
    public String desc;
    private double price = 0.0;

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public abstract double cost();
}


package decorator.demo_coffee;

/**
 * @author QiuQian
 */
public class Coffee extends Drink {

    @Override
    public double cost() {
        return super.getPrice();
    }
}


package decorator.demo_coffee;

/**
 * @author QiuQian
 * 具体构建角色
 */
public class Espresso extends Coffee {
    public Espresso() {
        setDesc("Espresso");
        setPrice(16);
    }
}


package decorator.demo_coffee;

/**
 * @author QiuQian
 * 具体构建角色
 */
public class Latte extends Coffee {
    public Latte() {
        setDesc("Latte");
        setPrice(25);
    }
}


package decorator.demo_coffee;

/**
 * @author QiuQian
 * 具体构建角色
 */
public class LongBlack extends Coffee {
    public LongBlack() {
        setDesc("LongBlack");
        setPrice(18);
    }
}


package decorator.demo_coffee;

/**
 * @author QiuQian
 * 抽象装饰角色
 */
public class Decorator extends Drink {
    private Drink drink;

    public Decorator(Drink drink) {
        this.drink = drink;
    }

    @Override
    public double cost() {
        // getPrice() Decorator
        return getPrice() + drink.cost();
    }

    @Override
    public String getDesc() {
        return desc + getPrice() + " + " + drink.getDesc();
    }
}



package decorator.demo_coffee;

/**
 * @author QiuQian
 * 具体装饰角色
 */
public class Milk extends Decorator {
    public Milk(Drink drink) {
        super(drink);
        setDesc("Milk");
        setPrice(8);
    }
}



package decorator.demo_coffee;

/**
 * @author QiuQian
 */
public class Client {
    public static void main(String[] args) {
        Drink order = new Latte();
        order = new Milk(order);
        System.out.println(order.getDesc());
        System.out.println(order.cost());

        System.out.println("====================");

        Drink order2 = new Espresso();
        order2 = new Milk(order2);
        System.out.println(order2.getDesc());
        System.out.println(order2.cost());

        System.out.println("====================");

        Drink order3 = new LongBlack();
        order3 = new Milk(order3);
        System.out.println(order3.getDesc());
        System.out.println(order3.cost());

    }
}

运行结果

image-20210512131728660


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!