装饰模式(Decorator Pattern)是一种结构型设计模式,它允许你动态地为对象添加额外的功能,而不需要修改其源代码。这种模式属于设计模式中的包装模式,它通过将对象包装在装饰器类中来实现。
装饰模式的核心思想是以透明的方式扩展对象的功能,同时保持其接口不变。这意味着客户端可以使用原始对象或经过装饰器包装后的对象,而无需关心其具体类型。
以下是一些与装饰模式相关的概念:
-
组件(Component):这是一个抽象类或接口,定义了对象的基本接口。具体组件和装饰器都实现了这个接口。
-
具体组件(Concrete Component):这是实现组件接口的具体类,它是装饰模式中的原始对象,可以被装饰器包装。
-
装饰器(Decorator):装饰器是一个抽象类,它实现了组件接口,并包含一个对组件对象的引用。装饰器通常提供了一些额外的操作,然后将请求委派给组件。
-
具体装饰器(Concrete Decorator):这是实现装饰器接口的具体类,它添加了具体的功能或状态到组件。它可以包装其他装饰器或具体组件。
现在,让我举一个实际的装饰模式应用场景,并提供相关代码和详细描述。
场景:咖啡店中的咖啡订单
在一个咖啡店中,我们有不同种类的咖啡,例如浓缩咖啡、拿铁咖啡、摩卡咖啡等。客户可以根据需要选择不同种类的咖啡,并选择是否要添加额外的配料,如牛奶、糖和巧克力。我们将使用装饰模式来动态添加配料,而不需要创建大量的咖啡类。
首先,定义基本的咖啡接口:
public interface Coffee {double cost();
}
然后,创建具体的咖啡类:
public class Espresso implements Coffee {@Overridepublic double cost() {return 1.99;}
}public class Latte implements Coffee {@Overridepublic double cost() {return 2.49;}
}// 其他咖啡类...
接下来,创建装饰器类来扩展咖啡功能:
public abstract class CoffeeDecorator implements Coffee {private Coffee coffee;public CoffeeDecorator(Coffee coffee) {this.coffee = coffee;}@Overridepublic double cost() {return coffee.cost();}
}public class MilkDecorator extends CoffeeDecorator {public MilkDecorator(Coffee coffee) {super(coffee);}@Overridepublic double cost() {return super.cost() + 0.5; // 添加牛奶的费用}
}public class SugarDecorator extends CoffeeDecorator {public SugarDecorator(Coffee coffee) {super(coffee);}@Overridepublic double cost() {return super.cost() + 0.2; // 添加糖的费用}
}// 其他装饰器类...
现在,客户可以根据需要创建各种咖啡并动态添加配料:
public class CoffeeShop {public static void main(String[] args) {Coffee espresso = new Espresso();Coffee latteWithMilk = new MilkDecorator(new Latte());Coffee mochaWithMilkAndSugar = new SugarDecorator(new MilkDecorator(new Mocha()));System.out.println("Espresso cost: " + espresso.cost());System.out.println("Latte with milk cost: " + latteWithMilk.cost());System.out.println("Mocha with milk and sugar cost: " + mochaWithMilkAndSugar.cost());}
}
在这个示例中,装饰模式允许我们动态地为不同种类的咖啡添加不同的配料,而不需要创建大量的组合类。这提供了灵活性和可维护性,是一个典型的装饰模式应用场景。