Decorator using Java 8

Wikipedia has a sample decorator here:

https://en.wikipedia.org/wiki/Decorator_pattern#Second_example_.28coffee_making_scenario.29

I tried to solve this using a functional style using Java 8, the solution I chose:

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";
        }
    };
}

}

Now I am not so convinced of the decision in CoffeeIngredientCalculator. If we had one responsibility in the Coffee interface, getCost (), using the functional style and applying the decorator pattern seems much better and cleaner. It would basically come down to Function<Double,Double>, we don’t need an abstract class, separate decorators and just chains of functions.

, 2 Coffee, , , , .

:

1) ?

2) , ?

3) GOF , , , ?

+4
2

, :

  • ,
  • / Coffee. . Coffee , , .
  • , GoF . , .

: , private static - . , .

+3

.

, equals, hashCode, toString,

return new Coffee(coffee.getCost() + 0.2, coffee.getIngredients() + ", Sprinkles");

factory

return coffee(coffee.getCost() + 0.2, coffee.getIngredients() + ", Sprinkles");

(, immutables)

return coffee
    .withCost(coffee.getCost() + 0.2) //new instance
    .withIngredients(coffee.getIngredients() + ", Sprinkles"); //another new instance
+2

Source: https://habr.com/ru/post/1649361/


All Articles