#111 Implementation of Step Builder pattern
This commit is contained in:
BIN
step-builder/etc/step-builder.png
Normal file
BIN
step-builder/etc/step-builder.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 74 KiB |
181
step-builder/etc/step-builder.ucls
Normal file
181
step-builder/etc/step-builder.ucls
Normal file
@ -0,0 +1,181 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<class-diagram version="1.1.8" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"
|
||||
realizations="true" associations="true" dependencies="true" nesting-relationships="false">
|
||||
<interface id="1" language="java" name="com.iluwatar.stepbuilder.CharacterStepBuilder.SpellStep"
|
||||
project="step-builder" file="/step-builder/src/main/java/com/iluwatar/stepbuilder/CharacterStepBuilder.java"
|
||||
binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="301" y="280"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</interface>
|
||||
<class id="2" language="java" name="com.iluwatar.stepbuilder.CharacterStepBuilder.CharacterSteps"
|
||||
project="step-builder" file="/step-builder/src/main/java/com/iluwatar/stepbuilder/CharacterStepBuilder.java"
|
||||
binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="95" y="345"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<class id="3" language="java" name="com.iluwatar.stepbuilder.CharacterStepBuilder" project="step-builder"
|
||||
file="/step-builder/src/main/java/com/iluwatar/stepbuilder/CharacterStepBuilder.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="92" y="56"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<interface id="4" language="java" name="com.iluwatar.stepbuilder.CharacterStepBuilder.AbilityStep"
|
||||
project="step-builder" file="/step-builder/src/main/java/com/iluwatar/stepbuilder/CharacterStepBuilder.java"
|
||||
binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="409" y="418"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</interface>
|
||||
<interface id="5" language="java" name="com.iluwatar.stepbuilder.CharacterStepBuilder.ClassStep"
|
||||
project="step-builder" file="/step-builder/src/main/java/com/iluwatar/stepbuilder/CharacterStepBuilder.java"
|
||||
binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="406" y="163"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</interface>
|
||||
<interface id="6" language="java" name="com.iluwatar.stepbuilder.CharacterStepBuilder.WeaponStep"
|
||||
project="step-builder" file="/step-builder/src/main/java/com/iluwatar/stepbuilder/CharacterStepBuilder.java"
|
||||
binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="509" y="279"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</interface>
|
||||
<interface id="7" language="java" name="com.iluwatar.stepbuilder.CharacterStepBuilder.NameStep" project="step-builder"
|
||||
file="/step-builder/src/main/java/com/iluwatar/stepbuilder/CharacterStepBuilder.java" binary="false"
|
||||
corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="404" y="49"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</interface>
|
||||
<interface id="8" language="java" name="com.iluwatar.stepbuilder.CharacterStepBuilder.BuildStep"
|
||||
project="step-builder" file="/step-builder/src/main/java/com/iluwatar/stepbuilder/CharacterStepBuilder.java"
|
||||
binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="412" y="550"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</interface>
|
||||
<class id="9" language="java" name="com.iluwatar.stepbuilder.Character" project="step-builder"
|
||||
file="/step-builder/src/main/java/com/iluwatar/stepbuilder/Character.java" binary="false" corner="BOTTOM_RIGHT">
|
||||
<position height="-1" width="-1" x="710" y="217"/>
|
||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</display>
|
||||
</class>
|
||||
<realization id="10">
|
||||
<bendpoint x="252" y="168"/>
|
||||
<end type="SOURCE" refId="2"/>
|
||||
<end type="TARGET" refId="5"/>
|
||||
</realization>
|
||||
<realization id="11">
|
||||
<bendpoint x="255" y="419"/>
|
||||
<end type="SOURCE" refId="2"/>
|
||||
<end type="TARGET" refId="4"/>
|
||||
</realization>
|
||||
<realization id="12">
|
||||
<bendpoint x="197" y="123"/>
|
||||
<end type="SOURCE" refId="2"/>
|
||||
<end type="TARGET" refId="7"/>
|
||||
</realization>
|
||||
<dependency id="13">
|
||||
<end type="SOURCE" refId="3"/>
|
||||
<end type="TARGET" refId="7"/>
|
||||
</dependency>
|
||||
<dependency id="14">
|
||||
<end type="SOURCE" refId="5"/>
|
||||
<end type="TARGET" refId="1"/>
|
||||
</dependency>
|
||||
<realization id="15">
|
||||
<bendpoint x="398" y="346"/>
|
||||
<end type="SOURCE" refId="2"/>
|
||||
<end type="TARGET" refId="6"/>
|
||||
</realization>
|
||||
<dependency id="16">
|
||||
<end type="SOURCE" refId="7"/>
|
||||
<end type="TARGET" refId="5"/>
|
||||
</dependency>
|
||||
<realization id="17">
|
||||
<bendpoint x="261" y="554"/>
|
||||
<end type="SOURCE" refId="2"/>
|
||||
<end type="TARGET" refId="8"/>
|
||||
</realization>
|
||||
<dependency id="18">
|
||||
<end type="SOURCE" refId="3"/>
|
||||
<end type="TARGET" refId="2"/>
|
||||
</dependency>
|
||||
<dependency id="19">
|
||||
<end type="SOURCE" refId="1"/>
|
||||
<end type="TARGET" refId="4"/>
|
||||
</dependency>
|
||||
<dependency id="20">
|
||||
<bendpoint x="512" y="477"/>
|
||||
<end type="SOURCE" refId="6"/>
|
||||
<end type="TARGET" refId="8"/>
|
||||
</dependency>
|
||||
<dependency id="21">
|
||||
<end type="SOURCE" refId="4"/>
|
||||
<end type="TARGET" refId="8"/>
|
||||
</dependency>
|
||||
<realization id="22">
|
||||
<end type="SOURCE" refId="2"/>
|
||||
<end type="TARGET" refId="1"/>
|
||||
</realization>
|
||||
<dependency id="23">
|
||||
<bendpoint x="597" y="547"/>
|
||||
<end type="SOURCE" refId="8"/>
|
||||
<end type="TARGET" refId="9"/>
|
||||
</dependency>
|
||||
<dependency id="24">
|
||||
<bendpoint x="97" y="602"/>
|
||||
<bendpoint x="712" y="596"/>
|
||||
<end type="SOURCE" refId="2"/>
|
||||
<end type="TARGET" refId="9"/>
|
||||
</dependency>
|
||||
<dependency id="25">
|
||||
<end type="SOURCE" refId="5"/>
|
||||
<end type="TARGET" refId="6"/>
|
||||
</dependency>
|
||||
<dependency id="26">
|
||||
<end type="SOURCE" refId="6"/>
|
||||
<end type="TARGET" refId="4"/>
|
||||
</dependency>
|
||||
<dependency id="27">
|
||||
<bendpoint x="303" y="475"/>
|
||||
<end type="SOURCE" refId="1"/>
|
||||
<end type="TARGET" refId="8"/>
|
||||
</dependency>
|
||||
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||
sort-features="false" accessors="true" visibility="true">
|
||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||
</classifier-display>
|
||||
<association-display labels="true" multiplicity="true"/>
|
||||
</class-diagram>
|
19
step-builder/pom.xml
Normal file
19
step-builder/pom.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<version>1.5.0</version>
|
||||
</parent>
|
||||
<artifactId>step-builder</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
69
step-builder/src/main/java/com/iluwatar/stepbuilder/App.java
Normal file
69
step-builder/src/main/java/com/iluwatar/stepbuilder/App.java
Normal file
@ -0,0 +1,69 @@
|
||||
package com.iluwatar.stepbuilder;
|
||||
|
||||
/**
|
||||
* Step Builder Pattern
|
||||
*
|
||||
* <p><b>Intent</b>
|
||||
* <br/>
|
||||
* An extension of the Builder pattern that fully guides the user
|
||||
* through the creation of the object with no chances of confusion.
|
||||
* <br/>
|
||||
* The user experience will be much more improved by the fact that
|
||||
* he will only see the next step methods available, NO build method
|
||||
* until is the right time to build the object.
|
||||
*
|
||||
* <p><b>Implementation</b>
|
||||
* </br>
|
||||
* <ul>The concept is simple:
|
||||
*
|
||||
* <li>Write creational steps inner classes or interfaces where each
|
||||
* method knows what can be displayed next.</li>
|
||||
*
|
||||
* <li>Implement all your steps interfaces in an inner static class.</li>
|
||||
*
|
||||
* <li>Last step is the BuildStep, in charge of creating the object
|
||||
* you need to build.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p><b>Applicability</b>
|
||||
* <br/>
|
||||
* Use the Step Builder pattern when the algorithm for creating a
|
||||
* complex object should be independent of the parts that make up
|
||||
* the object and how they're assembled the construction process must
|
||||
* allow different representations for the object that's constructed
|
||||
* when in the process of constructing the order is important.
|
||||
*
|
||||
* http://rdafbn.blogspot.co.uk/2012/07/step-builder-pattern_28.html
|
||||
*/
|
||||
public class App {
|
||||
public static void main(String[] args) {
|
||||
|
||||
Character warrior = CharacterStepBuilder.newBuilder()
|
||||
.name("Amberjill")
|
||||
.fighterClass("Paladin")
|
||||
.withWeapon("Sword")
|
||||
.noAbilities()
|
||||
.build();
|
||||
|
||||
System.out.println(warrior);
|
||||
|
||||
Character mage = CharacterStepBuilder.newBuilder()
|
||||
.name("Riobard")
|
||||
.wizardClass("Sorcerer")
|
||||
.withSpell("Fireball")
|
||||
.withAbility("Fire Aura")
|
||||
.withAbility("Teleport")
|
||||
.noMoreAbilities()
|
||||
.build();
|
||||
|
||||
System.out.println(mage);
|
||||
|
||||
Character thief = CharacterStepBuilder.newBuilder()
|
||||
.name("Desmond")
|
||||
.fighterClass("Rogue")
|
||||
.noWeapon()
|
||||
.build();
|
||||
|
||||
System.out.println(thief);
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package com.iluwatar.stepbuilder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The class with many parameters.
|
||||
*/
|
||||
public class Character {
|
||||
|
||||
private String name;
|
||||
private String fighterClass;
|
||||
private String wizardClass;
|
||||
private String weapon;
|
||||
private String spell;
|
||||
private List<String> abilities;
|
||||
|
||||
public Character(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getFighterClass() {
|
||||
return fighterClass;
|
||||
}
|
||||
|
||||
public void setFighterClass(String fighterClass) {
|
||||
this.fighterClass = fighterClass;
|
||||
}
|
||||
|
||||
public String getWizardClass() {
|
||||
return wizardClass;
|
||||
}
|
||||
|
||||
public void setWizardClass(String wizardClass) {
|
||||
this.wizardClass = wizardClass;
|
||||
}
|
||||
|
||||
public String getWeapon() {
|
||||
return weapon;
|
||||
}
|
||||
|
||||
public void setWeapon(String weapon) {
|
||||
this.weapon = weapon;
|
||||
}
|
||||
|
||||
public String getSpell() {
|
||||
return spell;
|
||||
}
|
||||
|
||||
public void setSpell(String spell) {
|
||||
this.spell = spell;
|
||||
}
|
||||
|
||||
public List<String> getAbilities() {
|
||||
return abilities;
|
||||
}
|
||||
|
||||
public void setAbilities(List<String> abilities) {
|
||||
this.abilities = abilities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("This is a ");
|
||||
sb.append(fighterClass != null ? fighterClass : wizardClass);
|
||||
sb.append(" named a ");
|
||||
sb.append(name);
|
||||
sb.append(" armed ");
|
||||
sb.append(weapon != null ? weapon : spell != null ? spell : "with nothing");
|
||||
sb.append(abilities != null ? (" and wielding " + abilities + " abilities") : "");
|
||||
sb.append(".");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,168 @@
|
||||
package com.iluwatar.stepbuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The Step Builder class.
|
||||
*/
|
||||
|
||||
public class CharacterStepBuilder {
|
||||
|
||||
private CharacterStepBuilder() {
|
||||
}
|
||||
|
||||
public static NameStep newBuilder() {
|
||||
return new CharacterSteps();
|
||||
}
|
||||
|
||||
/**
|
||||
* First Builder Step in charge of the Character name.
|
||||
* Next Step available : ClassStep
|
||||
*/
|
||||
public interface NameStep {
|
||||
ClassStep name(String name);
|
||||
}
|
||||
|
||||
/**
|
||||
* This step is in charge of setting the Character class (fighter or wizard).
|
||||
* Fighter choice : Next Step available : WeaponStep
|
||||
* Wizard choice : Next Step available : SpellStep
|
||||
*/
|
||||
public interface ClassStep {
|
||||
WeaponStep fighterClass(String fighterClass);
|
||||
SpellStep wizardClass(String wizardClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* This step is in charge of the weapon.
|
||||
* Weapon choice : Next Step available : AbilityStep
|
||||
* No weapon choice : Next Step available : BuildStep
|
||||
*/
|
||||
public interface WeaponStep {
|
||||
AbilityStep withWeapon(String weapon);
|
||||
BuildStep noWeapon();
|
||||
}
|
||||
|
||||
/**
|
||||
* This step is in charge of the spell.
|
||||
* Spell choice : Next Step available : AbilityStep
|
||||
* No spell choice : Next Step available : BuildStep
|
||||
*/
|
||||
public interface SpellStep {
|
||||
AbilityStep withSpell(String spell);
|
||||
BuildStep noSpell();
|
||||
}
|
||||
|
||||
/**
|
||||
* This step is in charge of abilities.
|
||||
* Next Step available : BuildStep
|
||||
*/
|
||||
public interface AbilityStep {
|
||||
AbilityStep withAbility(String ability);
|
||||
BuildStep noMoreAbilities();
|
||||
BuildStep noAbilities();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the final step in charge of building the Character Object.
|
||||
* Validation should be here.
|
||||
*/
|
||||
public interface BuildStep {
|
||||
Character build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Step Builder implementation.
|
||||
*/
|
||||
private static class CharacterSteps
|
||||
implements NameStep, ClassStep, WeaponStep, SpellStep, AbilityStep, BuildStep {
|
||||
|
||||
private String name;
|
||||
private String fighterClass;
|
||||
private String wizardClass;
|
||||
private String weapon;
|
||||
private String spell;
|
||||
private List<String> abilities = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public ClassStep name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeaponStep fighterClass(String fighterClass) {
|
||||
this.fighterClass = fighterClass;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpellStep wizardClass(String wizardClass) {
|
||||
this.wizardClass = wizardClass;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbilityStep withWeapon(String weapon) {
|
||||
this.weapon = weapon;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuildStep noWeapon() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbilityStep withSpell(String spell) {
|
||||
this.spell = spell;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuildStep noSpell() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbilityStep withAbility(String ability) {
|
||||
this.abilities.add(ability);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuildStep noMoreAbilities() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuildStep noAbilities() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Character build() {
|
||||
Character character = new Character(name);
|
||||
|
||||
if (fighterClass != null) {
|
||||
character.setFighterClass(fighterClass);
|
||||
} else {
|
||||
character.setWizardClass(wizardClass);
|
||||
}
|
||||
|
||||
if (weapon != null) {
|
||||
character.setWeapon(weapon);
|
||||
} else {
|
||||
character.setSpell(spell);
|
||||
}
|
||||
|
||||
if (!abilities.isEmpty()) {
|
||||
character.setAbilities(abilities);
|
||||
}
|
||||
|
||||
return character;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.iluwatar.stepbuilder;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class AppTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user