Wikipedia在这里有一个装饰模式的例子:
https://en.wikipedia.org/wiki/Decorator_pattern#Second_example_.28coffee_making_scenario.29
我试图使用Java 8解决这个问题,我提出了解决方案:
1.CoffeeDecorator.java
public class CoffeeDecorator {
public static Coffee getCoffee(Coffee basicCoffee, Function<Coffee, Coffee>... coffeeIngredients) {
Function<Coffee, Coffee> chainOfFunctions = Stream.of(coffeeIngredients)
.reduce(Function.identity(),Function::andThen);
return chainOfFunctions.apply(basicCoffee);
}
public static void main(String args[]) {
Coffee simpleCoffee = new SimpleCoffee();
printInfo(simpleCoffee);
Coffee coffeeWithMilk = CoffeeDecorator.getCoffee(simpleCoffee, CoffeeIngredientCalculator::withMilk);
printInfo(coffeeWithMilk);
Coffee coffeeWithWSprinkle = CoffeeDecorator.getCoffee(coffeeWithMilk,CoffeeIngredientCalculator::withSprinkles);
printInfo(coffeeWithWSprinkle);
}
public static void printInfo(Coffee c) {
System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());
}
}
2.CoffeeIngredientCalculator.java
public class CoffeeIngredientCalculator {
public static Coffee withMilk(Coffee coffee) {
return new Coffee() {
@Override
public double getCost() {
return coffee.getCost() + 0.5;
}
@Override
public String getIngredients() {
return coffee.getIngredients() + " , Milk";
}
};
}
public static Coffee withSprinkles(Coffee coffee) {
return new Coffee() {
@Override
public double getCost() {
return coffee.getCost() + 0.2;
}
@Override
public String getIngredients() {
return coffee.getIngredients() + " , Sprinkles";
}
};
}
}
现在,我对CoffeeIngredientCalculator中的解决方案并不那么信服。如果我们在Coffee界面中有一个责任,getCost(),使用功能样式并应用装饰器模式似乎更好,更清洁。它基本上归结为Function<Double,Double>
,我们不需要抽象类,单独的装饰器,只能链接函数。
但是在咖啡示例中,对于Coffee对象的成本和描述有两种行为,我并不相信这是一个重要的增值,因为我们正在创建一个匿名类,覆盖了2个方法。
问题:
1)这个解决方案是否可以接受?
2)如果没有,是否有更好的方法使用功能样式来解决它?
3)在我们正在装饰的对象有多种方法的场景中,我们是否应该遵循通常的GOF方式来设置抽象类和单独的装饰器类?
答案 0 :(得分:3)
所以,快速回答:
Coffee
方法。取决于您的要求。由于Coffee
不是一个功能接口,即具有多个方法,因此您必须回到普通的旧子类。最后一点:如果您不喜欢匿名课程,那么您可以编写private static
内部课程,或者其他任何内容。一个更紧凑,另一个用垃圾收集器更好。
答案 1 :(得分:2)
您的解决方案是可以接受的。
出于实际原因,例如hashCode
,toString
,return new Coffee(coffee.getCost() + 0.2, coffee.getIngredients() + ", Sprinkles");
的单一实施,我会用
构造
return coffee(coffee.getCost() + 0.2, coffee.getIngredients() + ", Sprinkles");
工厂方法
return coffee
.withCost(coffee.getCost() + 0.2) //new instance
.withIngredients(coffee.getIngredients() + ", Sprinkles"); //another new instance
甚至复制方法(如immutables)
highlight_text()