Created
July 13, 2016 07:37
-
-
Save michael-simons/1f9a6ae42f78b2a024b84e0248dd74c6 to your computer and use it in GitHub Desktop.
Sandwich example for https://jaxenter.de/pattern-java-8-lambda-43323
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package patternexamples; | |
import java.util.ArrayList; | |
import java.util.Collections; | |
import java.util.List; | |
import java.util.function.Function; | |
public class Sandwich { | |
private final String bread; | |
private final String meat; | |
private final String cheese; | |
private final List<String> vegetables; | |
private Sandwich(Builder builder) { | |
this.bread = builder.bread; | |
this.meat = builder.meat; | |
this.cheese = builder.cheese; | |
this.vegetables = Collections.unmodifiableList(builder.vegetables); | |
} | |
public String getBread() { | |
return bread; | |
} | |
public String getCheese() { | |
return cheese; | |
} | |
public String getMeat() { | |
return meat; | |
} | |
public List<String> getVegetables() { | |
return vegetables; | |
} | |
public Sandwich withAdditionalVeggies(final String vegetable) { | |
return new Builder(this).addVeggie(vegetable).close().create(); | |
} | |
public Sandwich withCheese(final String cheese) { | |
return new Builder(this).withCheese(cheese).noVeggies().create(); | |
} | |
public Sandwich removeCheese() { | |
return new Builder(this).noCheese().close().create(); | |
} | |
public static interface ChooseBreadStep { | |
public ChooseMeatStep withMeat(final String meat); | |
public AddVeggiesStep vegan(); | |
} | |
public static interface ChooseMeatStep { | |
public ChooseCheeseStep withCheese(final String cheese); | |
public AddVeggiesStep noCheese(); | |
} | |
public static interface ChooseCheeseStep { | |
public AddVeggiesStep addVeggie(final String vegetable); | |
public CloseStep noVeggies(); | |
} | |
public static interface AddVeggiesStep { | |
public AddVeggiesStep addVeggie(final String vegetable); | |
public CloseStep close(); | |
} | |
public static interface CloseStep { | |
public Sandwich create(); | |
} | |
private static class Builder implements ChooseBreadStep, ChooseMeatStep, ChooseCheeseStep, AddVeggiesStep, CloseStep { | |
final String bread; | |
String meat; | |
String cheese; | |
final List<String> vegetables = new ArrayList<>(); | |
Builder(String bread) { | |
this.bread = bread; | |
} | |
Builder(Sandwich template) { | |
this.bread = template.bread; | |
this.meat = template.meat; | |
this.cheese = template.cheese; | |
this.vegetables.addAll(template.vegetables); | |
} | |
@Override | |
public ChooseMeatStep withMeat(String meat) { | |
this.meat = meat; | |
return this; | |
} | |
@Override | |
public AddVeggiesStep vegan() { | |
return this; | |
} | |
@Override | |
public ChooseCheeseStep withCheese(String cheese) { | |
this.cheese = cheese; | |
return this; | |
} | |
@Override | |
public AddVeggiesStep noCheese() { | |
this.cheese = null; | |
return this; | |
} | |
@Override | |
public AddVeggiesStep addVeggie(String vegetable) { | |
this.vegetables.add(vegetable); | |
return this; | |
} | |
@Override | |
public CloseStep noVeggies() { | |
return this; | |
} | |
@Override | |
public CloseStep close() { | |
return this; | |
} | |
@Override | |
public Sandwich create() { | |
return new Sandwich(this); | |
} | |
} | |
public static Sandwich make(String bread, Function<ChooseBreadStep, CloseStep> configuration) { | |
return configuration.andThen(CloseStep::create).apply(new Builder(bread)); | |
} | |
public static void main(final String...a) { | |
Sandwich.make("white", cfg -> cfg | |
.withMeat("parma") | |
.withCheese("cheedar") | |
.addVeggie("salad") | |
.close() | |
); | |
Sandwich.make("brown", cfg -> cfg | |
.withMeat("salami") | |
.noCheese() | |
.close()); | |
Sandwich.make("spelt", cfg -> cfg | |
.vegan() | |
.addVeggie("salad") | |
.addVeggie("gherkins") | |
.addVeggie("tomatoes") | |
.close() | |
); | |
Sandwich sandwich = Sandwich.make("white", cfg -> cfg | |
.withMeat("parma") | |
.withCheese("cheedar") | |
.addVeggie("salad") | |
.close() | |
); | |
sandwich = sandwich.removeCheese(); | |
assert(sandwich.meat.equals("parma") && sandwich.cheese == null && sandwich.vegetables.size() == 1); | |
sandwich = sandwich | |
.withAdditionalVeggies("tomatoes") | |
.withCheese("gouda"); | |
assert(sandwich.meat.equals("parma") && sandwich.cheese.equals("gouda") && sandwich.vegetables.size() == 2); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment