装饰者模式

48 阅读3分钟

装饰者模式

装饰者模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。它是作为现有的类的一个包装。装饰器模式通过将对象包装在装饰器类中,以便动态地修改其行为。


结构

  • 抽象构件角色:使用抽象接口用来规范准备接受附加责任的对象。
  • 具体构件角色:即被装饰的对象。
  • 抽象装饰角色:继承或实现抽象构件,并包含具体构件的实例,子类扩展具体构件功能。
  • 具体装饰角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

image.png

代码

package wnan.decorator.component;

/*****UTF-8*****
 * Description: 快餐类 抽象构建角色
 * Author: wnan
 * Create Date: 2024/10/3 9:06
 * Proverbs: 吃得苦中苦,方为人上人
 */

public abstract class FastFood {
    private double price;
    private String desc;


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

    public double getPrice() {
        return price;
    }

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

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
    // 获得价格
    public abstract double cost();
}
package wnan.decorator.component;

/*****UTF-8*****
 * Description: 炒面 具体构件
 * Author: wnan
 * Create Date: 2024/10/3 9:34
 * Proverbs: 吃得苦中苦,方为人上人
 */
public class FriedNoodles extends FastFood{
    public FriedNoodles(){
        super(12, "炒面");
    }

    @Override
    public double cost() {
        return getPrice();
    }
}
package wnan.decorator.component;

/*****UTF-8*****
 * Description: 炒饭类 具体构件角色
 * Author: wnan
 * Create Date: 2024/10/3 9:14
 * Proverbs: 吃得苦中苦,方为人上人
 */
public class FrieRice extends FastFood{
    public FrieRice(){
        super(10, "炒饭");
    }

    @Override
    public double cost() {
        return getPrice();
    }
}
package wnan.decorator.decorator_;

import wnan.decorator.component.FastFood;

/*****UTF-8*****
 * Description: 抽象装饰角色
 * Author: wnan
 * Create Date: 2024/10/3 9:38
 * Proverbs: 吃得苦中苦,方为人上人
 */
public abstract class Garnish extends FastFood {
    private FastFood fastFood;

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

    public FastFood getFastFood() {
        return fastFood;
    }

    public void setFastFood(FastFood fastFood) {
        this.fastFood = fastFood;
    }
}
package wnan.decorator.decorator_;

import wnan.decorator.component.FastFood;

/*****UTF-8*****
 * Description: 鸡蛋 具体装饰角色
 * Author: wnan
 * Create Date: 2024/10/3 9:43
 * Proverbs: 吃得苦中苦,方为人上人
 */
public class Egg extends Garnish {
    public Egg(FastFood fastFood) {
        super(fastFood,1,"鸡蛋");
    }

    @Override
    public double cost() {
        // 当前鸡蛋+拿来装饰的快餐=总价格
        return getPrice()+getFastFood().cost();
    }

    @Override
    public String getDesc(){
        return super.getDesc()+getFastFood().getDesc();
    }
}
package wnan.decorator.decorator_;

import wnan.decorator.component.FastFood;

/*****UTF-8*****
 * Description: 培根 具体装饰角色
 * Author: wnan
 * Create Date: 2024/10/3 10:26
 * Proverbs: 吃得苦中苦,方为人上人
 */
public class Bacon extends Garnish{
    public Bacon(FastFood fastFood){
        super(fastFood,2,"培根");
    }

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

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

import wnan.decorator.component.FastFood;
import wnan.decorator.component.FrieRice;
import wnan.decorator.decorator_.Bacon;
import wnan.decorator.decorator_.Egg;

/*****UTF-8*****
 * Description: 装饰者模式
 * Author: wnan
 * Create Date: 2024/10/2 14:12
 * Proverbs: 吃得苦中苦,方为人上人
 */
public class Client {
    public static void main(String[] args) {
        FastFood rice = new FrieRice();
        System.out.println(rice.cost());
        System.out.println(rice.getPrice());
        System.out.println(rice.getDesc());

        FastFood rice_egg=new Egg(rice);
        System.out.println(rice_egg.cost());
        System.out.println(rice_egg.getPrice());
        System.out.println(rice_egg.getDesc());

        FastFood rice_egg_bacon = new Bacon(rice_egg);
        System.out.println(rice_egg_bacon.cost());
        System.out.println(rice_egg_bacon.getPrice());
        System.out.println(rice_egg_bacon.getDesc());
    }
}

运行结果:

10.0
10.0
炒饭
11.0
1.0
鸡蛋炒饭
13.0
2.0
培根鸡蛋炒饭

源码 design_pattern

优点

  • 低耦合:装饰类和被装饰类可以独立变化,互不影响。
  • 灵活性:可以动态地添加或撤销功能。
  • 替代继承:提供了一种继承之外的扩展对象功能的方式。