0
点赞
收藏
分享

微信扫一扫

Decorator装饰器

互联网码农 2022-04-18 阅读 89
java

定义

Decorator装饰器会动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

组成

  • 抽象构件(Component):核心,是一个接口或抽象类。
  • 具体构件(ConcreteComponent):Component的具体实现,需要被装饰的构建。
  • 装饰者(Decorator):继承或者实现Component,在它的属性里面有一个变量指向Component抽象构件。
  • 具体装饰者(ConcreteDecorator):可以把具体构件装饰成新的东西。

优缺点

优点

  • 装饰类和被装饰类可以独立发展,而不会相互耦合。
  • 装饰器模式是继承关系的一个替代方案,但就增加功能来说,装饰模式相比生成子类更为灵活。

缺点

  • 为了要装饰,会增加很多的小类,这些具体的装饰类的逻辑将不会非常的清晰直观,容易令人迷惑。
  • 如果进行了多层的装饰,排查错误时工作量会很大,需要一层一层的找下去。

使用场景

  • 当我们需要在不影响其他类的状况下,以动态、透明的方式为类添加功能。
  • 当不适合使用继承,又想进行方法扩展的时候。

示例

举一个手抓饼加菜的例子。

抽象构件(Component)

/**
 * 街边小吃
 */
public abstract class Snack {
    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;
    }

    //计算费用的抽象方法
    public abstract float cost();
}

基础构件(ConcreteComponent)

/**
 * 手抓饼
 */
public class HandGrabCake extends Snack {
    public HandGrabCake() {
        setPrice(5.0f);
        setDes("手抓饼(" + cost() + ")");
    }
		
    @Override
    public float cost() {
    	//需要被装饰的构建,所以只需要输出自己的价格
        return super.getPrice();
    }
}

装饰者(Decorator)

/**
 * 装饰者
 */
public class Decorator extends Snack {
    private Snack obj;
    public Decorator(Snack obj) { // 组合被装饰者的信息
        this.obj = obj;
    }
    @Override
    public float cost() {
        // 输出装饰后的价格
        return super.getPrice() + obj.cost();
    }

    @Override
    public String getDes() {
        // 输出装饰后的描述
        return des + "(" + getPrice() + ")&&" + obj.getDes();
    }
}

具体装饰者(ConcreteDecorator)

/**
 * 鸡蛋
 */
public class Egg extends Decorator {
    public Egg(Snack obj) {
        super(obj);
        setDes("鸡蛋");
        setPrice(1.0f);
    }
}
/**
 * 烤肠
 */
public class Sausage extends Decorator  {
    public Sausage(Snack obj) {
        super(obj);
        setDes("烤肠");
        setPrice(2.0f);
    }
}

Main

public class Main {
    public static void main(String[] args) {

        // 1. 点一份手抓饼
        Snack order = new HandGrabCake();
        System.out.println(order.getDes() + "=" + order.cost() + "元。");

        // 2. order 加入一个鸡蛋
        order = new Egg(order);
        System.out.println(order.getDes() + "=" + order.cost() + "元。");

        // 3. order 加入一根烤肠
        order = new Sausage(order);
        System.out.println(order.getDes() + "=" + order.cost() + "元。");
    }
}

-------输出结果----------
手抓饼(5.0)=5.0元。
鸡蛋(1.0)&&手抓饼(5.0)=6.0元。
烤肠(2.0)&&鸡蛋(1.0)&&手抓饼(5.0)=8.0元。
举报

相关推荐

0 条评论