美文网首页
8_装饰者模式

8_装饰者模式

作者: 真是个点子王 | 来源:发表于2021-01-12 10:20 被阅读0次
  • 在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。

结构

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

实例

  • 快餐店售卖炒面和炒饭,同时炒面和炒饭可以任意添加鸡蛋或者培根。
// 快餐类,抽象构建角色
// FastFood.java
public abstract class FastFood {
    private float price;
    private String desc;
    public FastFood() {
    }
    public FastFood(float price, String desc) {
        this.price = price;
        this.desc = desc;
    }
    public float getPrice() {
        return price;
    }
    public void setPrice(float price) {
        this.price = price;
    }
    public String getDesc() {
        return desc;
    }
    public void setDesc(String desc) {
        this.desc = desc;
    }
    public abstract float cost();
}

// 炒饭类,具体构件角色
// FriedRice.java
public class FriedRice extends FastFood{
    public FriedRice(){
        super(10,"炒饭");
    }

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

// 装饰者类,抽象装饰者角色
// Garnish.java
public class Garnish extends FastFood{
    private FastFood fastFood;
    
    public FastFood getFastFood() {
        return fastFood;
    }

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

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

// 鸡蛋类,具体的装饰角色
// Egg.java
public class Egg extends Garnish{
    public Egg(FastFood fastFood){
        super(fastFood,1,"鸡蛋");
    }
    @Override
    public float cost() {
        return getPrice() + getFastFood().cost();
    }
    @Override
    public String getDesc(){
        return super.getDesc() + getFastFood().getDesc();
    }
}

// Client.java
public class Client {
    public static void main(String[] args) {
        // 点一份炒饭
        FastFood food = new FriedRice();
        System.out.println(food.getDesc() + " " +food.cost() + "元");

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

        // 在上面的炒饭中加一个鸡蛋
        food = new Egg(food);
        System.out.println(food.getDesc() + " " +food.cost() + "元");

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

        // 在上面的炒饭中加一个鸡蛋
        food = new Egg(food);
        System.out.println(food.getDesc() + " " +food.cost() + "元");
    }
}
  • 对于装饰者模式,自己的理解是,装饰者和被装饰的构件首先都需要继承自同一个父类,这一点是为了满足向上转型其都能适配统一引用类型。
  • 其次,由于在装饰者内部通过了聚合的方式将抽象构建角色作为了自己的成员变量。这一步产生的结果是被装饰后的对象包含了本身的对象。而且,由于装饰者和被装饰的构件继承了同一父类,因此这种修饰包含的行为可以一层一层的发生。

优点

  • 装饰者模式可以带来比继承更加灵活的扩展功能,使用更加方便,可以通过组合不同的装饰者对象来获取具有不同行为状态的多样化的结构。装饰者模式比继承具有更好的扩展性,遵循了开闭原则;
  • 继承是静态的附加责任,装饰者是动态的附加责任;
  • 装饰者和被装饰者可以独立发展,不会相互耦合,装饰者模式是继承的一个替代模式,可以动态的扩展一个实现类的功能。

使用场景

  • 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统的扩展和维护时
    • 1、系统中存在大量独立的扩展,会导致大量的子类产生;
    • 2、类不能继承时,例如final
  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责;

与代理模式的区别

  • 相同点:
    • 都要实现与目标类相同的业务接口;
    • 在两个类中都要声明目标对象;
    • 都可以在不修改目标类的前提下增强目标方法;
  • 不同点:
    • 目的不同:装饰者的目的是为了增强目标对象,静态代理是为了保护和隐藏目标对象。

相关文章

  • 8_装饰者模式

    在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。 结构 抽象构件(Compen...

  • 如何利用装饰者模式在不改变原有对象的基础上扩展功能

    目录 什么是装饰者模式 普通示例 装饰者模式示例 类图关系 装饰者模式使用场景 装饰者模式优点 装饰者模式缺点 什...

  • 装饰者模式

    装饰者模式 装饰者模式和适配器模式对比 装饰者模式 是一种特别的适配器模式 装饰者与被装饰者都要实现同一个接口,主...

  • java IO 的知识总结

    装饰者模式 因为java的IO是基于装饰者模式设计的,所以要了解掌握IO 必须要先清楚什么事装饰者模式(装饰者模式...

  • 设计模式-装饰者模式

    装饰者模式概念: 装饰者模式又名包装(Wrapper)模式。装饰者模式以对客户端透明的方式扩展对象的功能,是继承关...

  • java - 装饰者模式

    装饰者模式 装饰者模式:动态将责任添加到对象上。如果需要扩展功能,装饰者提供了比继承更有弹性的解决方案。装饰者模式...

  • 设计模式之装饰者模式(Decorator Pattern)

    What: 装饰者模式又名包装(Wrapper)模式。装饰者模式动态地将责任附加到对象身上。若要扩展功能,装饰者提...

  • 装饰者(Decorator)模式

    装饰者(Decorator)模式装饰模式又名包装(Wrapper)模式。装饰模式是继承关系的一个替代方案。装饰模式...

  • 2、装饰者模式

    装饰者模式 一、基本概念 二、结构 三、案例1、装饰者模式案例2、JavaIO中使用装饰者模式 四、总结 一、基本...

  • PHP的设计模式-装饰者模式

    装饰者模式 装饰者模式 装饰者模式类似蛋糕,有草莓味、奶酪等种类,但是它们的核心都是蛋糕。 不断地将对象添加装饰的...

网友评论

      本文标题:8_装饰者模式

      本文链接:https://www.haomeiwen.com/subject/zvlsaktx.html