设计模式-装饰器模式
定义
装饰器模式是一种结构型设计模式,允许在不改变对象结构的情况下,动态地为对象添加新功能。
概念:
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种模式通过将对象包装在装饰器类中,以便动态地修改其行为。装饰器模式提供了一种灵活的替代继承方式来扩展功能,避免通过继承引入静态特征,特别是在子类数量急剧膨胀的情况下。
结构
- 组件接口(Component):定义一个接口,规定可以动态添加职责的对象标准。
- 具体组件(ConcreteComponent):实现该接口的具体类,提供基本功能。
- 抽象装饰者(Decorator):实现同样的接口,持有一个组件接口的引用,可以在任何时候动态的添加功能。
- 具体装饰者(ConcreteDecorator):扩展抽象装饰者,添加额外的职责。
应用场景
装饰器模式是一种强大的设计模式,适用于需要动态扩展对象功能的场景,能够有效提高代码的灵活性和可维护性。
- 动态添加功能:当需要在运行时动态的添加或者撤销对象的功能时,装饰器模式非常有用
- 避免类爆炸:在需要扩展类的功能但又不想通过继承的方式来实现时,装饰器模式可以有效避免类的数量急剧增加。
- 增强现有功能:可以在不修改现有代码情况下,增强现有功能。
示例
假设我们有一个基本的咖啡类 Coffee,我们可以通过装饰器模式为其添加不同的配料,如牛奶、糖等,而不需要为每种组合创建新的子类。每个配料都可以作为一个具体装饰者,动态地添加到咖啡对象中。
代码
/*** @ClassName Coffee* @Description 组件接口* @Author Feng* @Date 2025/6/15**/
public interface Coffee {double cost();String getDescription();
}
class SimpleCoffee implements Coffee {@Overridepublic double cost() {return 2.;}@Overridepublic String getDescription() {return "没加任何东西的咖啡";}
}
abstract class CoffeeDecorator implements Coffee{protected Coffee coffee;public CoffeeDecorator(Coffee coffee) {this.coffee = coffee;}@Overridepublic double cost() {return coffee.cost();}@Overridepublic String getDescription() {return coffee.getDescription();}
}
class MilkCoffee extends CoffeeDecorator{public MilkCoffee(Coffee coffee) {super(coffee);}@Overridepublic double cost() {return 4. + coffee.cost();}@Overridepublic String getDescription() {return coffee.getDescription() + "加了奶";}
}
class SugarCoffee extends CoffeeDecorator{public SugarCoffee(Coffee coffee) {super(coffee);}@Overridepublic double cost() {return 3. + coffee.cost();}@Overridepublic String getDescription() {return coffee.getDescription() + "加了糖";}
}
public class DecoratorTest {public static void main(String[] args) {SimpleCoffee simpleCoffee = new SimpleCoffee();System.out.println(simpleCoffee.getDescription() + " \t价格为:" + simpleCoffee.cost());// 加了糖的咖啡Coffee sugarCoffee = new SugarCoffee(simpleCoffee);System.out.println(sugarCoffee.getDescription() + " \t价格为:" + sugarCoffee.cost());// 加了奶的咖啡Coffee milkCoffee = new MilkCoffee(simpleCoffee);System.out.println(milkCoffee.getDescription() + " \t价格为:" + milkCoffee.cost());// 加了糖和奶的咖啡Coffee sugarMilkCoffee = new SugarCoffee(milkCoffee);System.out.println(sugarMilkCoffee.getDescription() + " \t价格为:" + sugarMilkCoffee.cost());}
}
优点
灵活性:可以在运行时动态的添加或者修改对象的功能
可扩展性:避免了通过继承引入的复杂性,提供了更好的扩展性和维护性。