/** * @program JavaBooks * @description: 装饰器模式 * @author: mf * @create: 2019/10/05 16:46 */ /* 按照单一职责原则,某一个对象只专注于干一件事,而如果要扩展其职能的话,不如想办法分离出一个类来“包装”这个对象,而这个扩展出的类则专注于实现扩展功能。 装饰器模式就可以将新功能动态地附加于现有对象而不改变现有对象的功能。 代理模式专注于对被代理对象的访问; 装饰器模式专注于对被装饰对象附加额外功能。 */ /* 假如有这样的一个需求 假设我去买咖啡,首先服务员给我冲了一杯原味咖啡,我希望服务员给我加些牛奶和白糖混合入原味咖啡中。使用装饰器模式就可以解决这个问题。 */ /** * 咖啡 */ interface Coffee { // 获取价格 double getCost(); // 获取配料 String getIngredients(); } /** * 原味咖啡 * cost:1 * 配料:只有咖啡 */ class SimpleCoffee implements Coffee { @Override public double getCost() { return 1; } @Override public String getIngredients() { return "Coffee"; } } /** * 咖啡对象的装饰器类 * 定义一个Coffe对象的引用,在构造器中进行初始化。并且将getCost()和getIntegredients()方法转发给被装饰对象。 */ abstract class CoffeeDecorator implements Coffee { protected final Coffee decoratedCoffee; /** * 在构造方法中,初始化咖啡对象的引用 */ protected CoffeeDecorator(Coffee coffee) { this.decoratedCoffee = coffee; } /** * 装饰器父类中直接转发"请求"至引用对象 */ public double getCost() { return decoratedCoffee.getCost(); } public String getIngredients() { return decoratedCoffee.getIngredients(); } } // 具体的装饰器类,负责往咖啡中“添加”牛奶,注意看getCost()方法和getIngredients()方法,可以在转发请求之前或者之后,增加功能。 // 如果是代理模式,这里的结构就有所不同,通常代理模式根据运行时的条件来判断是否转发请求。 /** * 此装饰类混合"牛奶"到原味咖啡中 */ class WithMilk extends CoffeeDecorator { public WithMilk(Coffee coffee) { super(coffee); } @Override public double getCost() { double additionalCost = 0.5; return super.getCost() + additionalCost; } @Override public String getIngredients() { String additionalIngredient = "milk"; return super.getIngredients() + ", " + additionalIngredient; } } class WithSugar extends CoffeeDecorator { public WithSugar(Coffee coffee) { super(coffee); } @Override public double getCost() { return super.getCost() + 1; } @Override public String getIngredients() { return super.getIngredients() + ", Sugar"; } } public class DecoratorMode { static void print(Coffee c) { System.out.println("花费了: " + c.getCost()); System.out.println("配料: " + c.getIngredients()); System.out.println("============"); } public static void main(String[] args) { //原味咖啡 Coffee c = new SimpleCoffee(); print(c); //增加牛奶的咖啡 c = new WithMilk(c); print(c); //再加一点糖 c = new WithSugar(c); print(c); } }