【发布时间】:2016-07-28 07:11:06
【问题描述】:
维基百科在这里有一个装饰器模式的例子:
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 种行为,我不太相信这是一个重要的增值,因为我们正在创建一个匿名类,覆盖这 2 个方法。
问题:
1) 这个解决方案可以接受吗?
2) 如果没有,有没有更好的方法来使用函数式风格来解决它?
3) 在我们正在装饰的对象有多个方法的情况下,我们是否应该坚持通常的 GOF 方式,即拥有一个抽象类和单独的装饰器类?
【问题讨论】:
-
这似乎更像是一个codereview.stackexchange.com 问题。
标签: design-patterns functional-programming java-8