欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > IT业 > 设计模式之 装饰者模式

设计模式之 装饰者模式

2024/11/30 10:56:28 来源:https://blog.csdn.net/2403_82445975/article/details/143936693  浏览:    关键词:设计模式之 装饰者模式

装饰者模式(Decorator Pattern)是一种结构型设计模式,它允许通过动态地给对象添加额外的功能,而不需要修改对象的结构。装饰者模式通过创建一个装饰类来封装原始对象,并为原始对象提供附加的功能。这种模式使得我们能够在运行时扩展对象的功能,避免了继承的局限性。

装饰者模式的核心思想是在不改变对象自身的情况下,给对象添加额外的职责。通过使用装饰者,可以使得对象的功能变得更加灵活,可以根据需要动态地添加功能。

一、装饰者模式的结构

装饰者模式的结构通常包括以下几个角色:

  1. 组件接口(Component)

    这是一个抽象的接口或类,它定义了被装饰的对象的基本功能。所有的具体组件(ConcreteComponent)和装饰者(Decorator)都需要实现或继承该接口。
  2. 具体组件(ConcreteComponent)

    具体组件是装饰者模式中的核心类,它实现了组件接口,并定义了具体的功能。它是被装饰的对象。
  3. 装饰者(Decorator)

    装饰者类是一个抽象类,它也实现了组件接口,并持有一个组件对象的引用。它的主要作用是通过在方法中调用组件对象的方法,然后再为其添加新的功能。
  4. 具体装饰者(ConcreteDecorator)

    具体装饰者是装饰者的子类,它在装饰者类的基础上,提供附加功能的实现。通过具体装饰者,可以实现不同的装饰功能。

二、装饰者模式的工作原理

装饰者模式的基本工作原理是:通过将一个组件(具体对象)传递给装饰者类,并通过装饰者来扩展其功能。装饰者类通常会持有一个指向组件接口的引用,这样就可以在不改变原有类的情况下,通过装饰者对象动态添加额外的功能。

装饰者模式可以理解为“在现有对象的外层包裹一个新的类”,通过组合的方式,而不是继承的方式,来扩展对象的功能。

三、装饰者模式的示例

示例:咖啡店

在咖啡店的业务中,我们可能需要为每一杯咖啡添加不同的配料(如牛奶、糖等)。我们可以使用装饰者模式来实现这个需求。

  • 抽象咖啡(组件接口)
    public class Coffee {private double price;private String 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 Coffee() {}public Coffee(double price, String desc) {this.price = price;this.desc = desc;}
    }
  • 具体咖啡(具体组件)
    public class Americano extends Coffee{public Americano() {super(10,"美式咖啡");}
    }
    public class Latte extends Coffee{public Latte() {super(8, "拿铁咖啡");}
    }
  •  装饰者类
    public class Decorator extends Coffee{private Coffee coffee;public Coffee getCoffee() {return coffee;}public void setCoffee(Coffee coffee) {this.coffee = coffee;}public Decorator(double price, String desc, Coffee coffee) {super(price, desc);this.coffee = coffee;}
    }
    
  •  具体装饰者(加糖,加奶)
    public class Sugar extends Decorator {public Sugar(Coffee coffee){super(1,"加糖",coffee);}@Overridepublic double getPrice() {return getCoffee().getPrice() + super.getPrice();}@Overridepublic String getDesc() {return getCoffee().getDesc() + super.getDesc();}
    }
    
    public class Milk extends Decorator{public Milk(Coffee coffee) {super(2, "加奶", coffee);}@Overridepublic double getPrice() {return getCoffee().getPrice() + super.getPrice();}@Overridepublic String getDesc() {return getCoffee().getDesc() + super.getDesc();}
    }
  •  测试类
    public class Client {public static void main(String[] args) {Coffee coffee = new Americano();System.out.println(coffee.getDesc() + ": " + coffee.getPrice());coffee = new Sugar(coffee);System.out.println(coffee.getDesc() + ": " + coffee.getPrice());coffee = new Milk(coffee);System.out.println(coffee.getDesc() + ": " + coffee.getPrice());}
    }
  •  运行结果
 
解释
  • Coffee是一个基础的咖啡类,定义了咖啡的基础属性
  • Decorator是装饰者类,它包装了一个Coffee对象
  • MilkSugar是具体装饰者类,它们分别为咖啡添加了牛奶和糖的费用。
  • 客户端可以选择性地给咖啡添加不同的装饰(例如,先加牛奶,再加糖),而且这些装饰类可以按需组合。

四、装饰者模式的优缺点

优点:
  1. 更灵活的扩展功能:

    • 装饰者模式可以在不修改原始类的情况下,动态地给对象添加新功能,从而增加了系统的灵活性。
  2. 避免了类的爆炸性增长:

    • 使用装饰者模式可以避免过多的继承层次结构,如果使用继承的话,会导致类的数量急剧增加。而通过装饰者,可以根据需要动态添加功能,保持系统结构的简洁性。
  3. 支持对象的职责分离:

    • 每个装饰者负责提供一个具体的功能,可以使得不同的功能职责分离,避免单一类承担过多的责任。
  4. 符合开闭原则:

    • 装饰者模式遵循了开闭原则,即对扩展开放,对修改封闭。通过装饰器,我们可以在不修改原始代码的情况下为对象添加新功能。
缺点:
  1. 增加了系统复杂度:

    • 由于使用了多个装饰类,可能会导致系统中装饰类的数量过多,增加了管理和理解的难度。
  2. 可能会使得代码变得难以追踪:

    • 因为装饰者会包裹原始对象并改变其行为,过多的装饰者链可能使得程序的行为变得难以理解和调试。
  3. 性能开销:

    • 每增加一个装饰者,都会增加一次方法调用的开销。如果装饰链很长,可能会影响性能。

五、装饰者模式的应用场景

装饰者模式适用于以下几种场景:

  1. 需要动态地为对象添加功能时:

    • 如果一个类需要动态地增加一些附加功能,而不是通过继承来实现,装饰者模式是一个很好的选择。
  2. 避免类的爆炸性增长:

    • 如果通过继承的方式去增加功能,会导致类的数量激增。使用装饰者模式,可以避免这种问题,并保持代码的简洁性。
  3. 功能可以独立扩展:

    • 如果对象的功能是可以独立扩展的,可以使用装饰者模式。在每个装饰类中,只负责某个特定功能的增强。
  4. 允许客户端按需增加功能:

    • 如果希望用户可以选择性地为对象增加某些功能,可以使用装饰者模式。每个装饰者都可以单独工作,也可以组合使用。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com