Merge branch 'master' of https://github.com/iluwatar/java-design-patterns
Conflicts: pom.xml
This commit is contained in:
commit
67a99ec3c2
87
README.md
87
README.md
@ -32,6 +32,7 @@ system independent of how its objects are created, composed, and represented.
|
||||
* [Prototype](#prototype)
|
||||
* [Property](#property)
|
||||
* [Singleton](#singleton)
|
||||
* [Step Builder](#step-builder)
|
||||
* [Multiton](#multiton)
|
||||
* [Object Pool](#object-pool)
|
||||
|
||||
@ -206,6 +207,14 @@ access to it.
|
||||
**Real world examples:**
|
||||
* [java.lang.Runtime#getRuntime()](http://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#getRuntime%28%29)
|
||||
|
||||
## <a name="step-builder">Step Builder</a> [↑](#list-of-design-patterns)
|
||||
**Intent:** An extension of the Builder pattern that fully guides the user through the creation of the object with no chances of confusion.
|
||||
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.
|
||||
|
||||

|
||||
|
||||
**Applicability:** 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.
|
||||
|
||||
## <a name="adapter">Adapter</a> [↑](#list-of-design-patterns)
|
||||
**Intent:** Convert the interface of a class into another interface the clients
|
||||
expect. Adapter lets classes work together that couldn't otherwise because of
|
||||
@ -307,8 +316,8 @@ are several common situations in which the Proxy pattern is applicable
|
||||
|
||||
**Typical Use Case:**
|
||||
|
||||
* Control access to another object
|
||||
* Lazy initialization
|
||||
* control access to another object
|
||||
* lazy initialization
|
||||
* implement logging
|
||||
* facilitate network connection
|
||||
* to count references to an object
|
||||
@ -334,7 +343,7 @@ improves the performance of application to great extent.
|
||||
|
||||
**Typical Use Case:**
|
||||
|
||||
* When network hits are expensive and time consuming
|
||||
* when network hits are expensive and time consuming
|
||||
* lookups of services are done quite frequently
|
||||
* large number of services are being used
|
||||
|
||||
@ -541,7 +550,7 @@ this behavior in the common parent class - it is defined once in the Servant.
|
||||

|
||||
|
||||
**Applicability:** Use the Servant pattern when
|
||||
* When we want some objects to perform a common action and don't want to define this action as a method in every class.
|
||||
* when we want some objects to perform a common action and don't want to define this action as a method in every class.
|
||||
|
||||
## <a name="null-object">Null Object</a> [↑](#list-of-design-patterns)
|
||||
**Intent:** In most object-oriented languages, such as Java or C#, references
|
||||
@ -556,7 +565,7 @@ Object is very predictable and has no side effects: it does nothing.
|
||||

|
||||
|
||||
**Applicability:** Use the Null Object pattern when
|
||||
* You want to avoid explicit null checks and keep the algorithm elegant and easy to read.
|
||||
* you want to avoid explicit null checks and keep the algorithm elegant and easy to read.
|
||||
|
||||
## <a name="event-aggregator">Event Aggregator</a> [↑](#list-of-design-patterns)
|
||||
**Intent:** A system with lots of objects can lead to complexities when a
|
||||
@ -569,7 +578,11 @@ allowing clients to register with just the aggregator.
|
||||

|
||||
|
||||
**Applicability:** Use the Event Aggregator pattern when
|
||||
* Event Aggregator is a good choice when you have lots of objects that are potential event sources. Rather than have the observer deal with registering with them all, you can centralize the registration logic to the Event Aggregator. As well as simplifying registration, a Event Aggregator also simplifies the memory management issues in using observers.
|
||||
* Event Aggregator is a good choice when you have lots of objects that are
|
||||
potential event sources. Rather than have the observer deal with registering
|
||||
with them all, you can centralize the registration logic to the Event
|
||||
Aggregator. As well as simplifying registration, a Event Aggregator also
|
||||
simplifies the memory management issues in using observers.
|
||||
|
||||
## <a name="callback">Callback</a> [↑](#list-of-design-patterns)
|
||||
**Intent:** Callback is a piece of executable code that is passed as an
|
||||
@ -579,7 +592,7 @@ at some convenient time.
|
||||

|
||||
|
||||
**Applicability:** Use the Callback pattern when
|
||||
* When some arbitrary synchronous or asynchronous action must be performed after execution of some defined activity.
|
||||
* when some arbitrary synchronous or asynchronous action must be performed after execution of some defined activity.
|
||||
|
||||
**Real world examples:**
|
||||
* [CyclicBarrier] (http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html#CyclicBarrier%28int,%20java.lang.Runnable%29) constructor can accept callback that will be triggered every time when barrier is tripped.
|
||||
@ -604,7 +617,7 @@ only what to do with the resource.
|
||||

|
||||
|
||||
**Applicability:** Use the Execute Around idiom when
|
||||
* You use an API that requires methods to be called in pairs such as open/close or allocate/deallocate.
|
||||
* you use an API that requires methods to be called in pairs such as open/close or allocate/deallocate.
|
||||
|
||||
## <a name="property">Property</a> [↑](#list-of-design-patterns)
|
||||
**Intent:** Create hierarchy of objects and new objects using already existing
|
||||
@ -667,8 +680,8 @@ order
|
||||

|
||||
|
||||
**Applicability:** Use the Specification pattern when
|
||||
* You need to select a subset of objects based on some criteria, and to refresh the selection at various times
|
||||
* You need to check that only suitable objects are used for a certain role (validation)
|
||||
* you need to select a subset of objects based on some criteria, and to refresh the selection at various times
|
||||
* you need to check that only suitable objects are used for a certain role (validation)
|
||||
|
||||
## <a name="tolerant-reader">Tolerant Reader</a> [↑](#list-of-design-patterns)
|
||||
**Intent:** Tolerant Reader is an integration pattern that helps creating
|
||||
@ -679,7 +692,7 @@ changes, the readers must not break.
|
||||

|
||||
|
||||
**Applicability:** Use the Tolerant Reader pattern when
|
||||
* The communication schema can evolve and change and yet the receiving side should not break
|
||||
* the communication schema can evolve and change and yet the receiving side should not break
|
||||
|
||||
## <a name="model-view-controller">Model-View-Controller</a> [↑](#list-of-design-patterns)
|
||||
**Intent:** Separate the user interface into three interconnected components:
|
||||
@ -701,7 +714,7 @@ logic, which updates all of the views that are affected.
|
||||

|
||||
|
||||
**Applicability:** Use the Flux pattern when
|
||||
* You want to focus on creating explicit and understandable update paths for your application's data, which makes tracing changes during development simpler and makes bugs easier to track down and fix.
|
||||
* you want to focus on creating explicit and understandable update paths for your application's data, which makes tracing changes during development simpler and makes bugs easier to track down and fix.
|
||||
|
||||
## <a name="double-dispatch">Double Dispatch</a> [↑](#list-of-design-patterns)
|
||||
**Intent:** Double Dispatch pattern is a way to create maintainable dynamic
|
||||
@ -710,7 +723,7 @@ behavior based on receiver and parameter types.
|
||||

|
||||
|
||||
**Applicability:** Use the Double Dispatch pattern when
|
||||
* The dynamic behavior is not defined only based on receiving object's type but also on the receiving method's parameter type.
|
||||
* the dynamic behavior is not defined only based on receiving object's type but also on the receiving method's parameter type.
|
||||
|
||||
**Real world examples:**
|
||||
* [ObjectOutputStream](https://docs.oracle.com/javase/8/docs/api/java/io/ObjectOutputStream.html)
|
||||
@ -742,7 +755,7 @@ and eliminating the latency of creating new threads.
|
||||

|
||||
|
||||
**Applicability:** Use the Thread Pool pattern when
|
||||
* You have a large number of short-lived tasks to be executed in parallel
|
||||
* you have a large number of short-lived tasks to be executed in parallel
|
||||
|
||||
## <a name="async-method-invocation">Async Method Invocation</a> [↑](#list-of-design-patterns)
|
||||
**Intent:** Asynchronous method invocation is pattern where the calling thread
|
||||
@ -753,9 +766,10 @@ callbacks or waiting until everything is done.
|
||||

|
||||
|
||||
**Applicability:** Use async method invocation pattern when
|
||||
* You have multiple independent tasks that can run in parallel
|
||||
* You need to improve performance of running a group of sequential tasks
|
||||
* You have limited number of processing capacity or long running tasks and the caller cannot wait the tasks to be ready
|
||||
* you have multiple independent tasks that can run in parallel
|
||||
* you need to improve the performance of a group of sequential tasks
|
||||
* you have limited amount of processing capacity or long running tasks and the
|
||||
caller should not wait the tasks to be ready
|
||||
|
||||
**Real world examples:**
|
||||
* [FutureTask](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/FutureTask.html), [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html) and [ExecutorService](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html) (Java)
|
||||
@ -769,7 +783,7 @@ attributes by encapsulating them in single Data object.
|
||||

|
||||
|
||||
**Applicability:** Use the Private Class Data pattern when
|
||||
* You want to prevent write access to class data members
|
||||
* you want to prevent write access to class data members
|
||||
|
||||
## <a name="object-pool">Object Pool</a> [↑](#list-of-design-patterns)
|
||||
**Intent:** When objects are expensive to create and they are needed only for
|
||||
@ -780,8 +794,8 @@ are in use and which are available.
|
||||

|
||||
|
||||
**Applicability:** Use the Object Pool pattern when
|
||||
* The objects are expensive to create (allocation cost)
|
||||
* You need a large number of short-lived objects (memory fragmentation)
|
||||
* the objects are expensive to create (allocation cost)
|
||||
* you need a large number of short-lived objects (memory fragmentation)
|
||||
|
||||
## <a name="dependency-injection">Dependency Injection</a> [↑](#list-of-design-patterns)
|
||||
**Intent:** Dependency Injection is a software design pattern in which one or
|
||||
@ -794,8 +808,8 @@ inversion of control and single responsibility principles.
|
||||

|
||||
|
||||
**Applicability:** Use the Dependency Injection pattern when
|
||||
* When you need to remove knowledge of concrete implementation from object
|
||||
* To enable unit testing of classes in isolation using mock objects or stubs
|
||||
* when you need to remove knowledge of concrete implementation from object
|
||||
* to enable unit testing of classes in isolation using mock objects or stubs
|
||||
|
||||
## <a name="naked-objects">Naked Objects</a> [↑](#list-of-design-patterns)
|
||||
**Intent:** The Naked Objects architectural pattern is well suited for rapid
|
||||
@ -805,9 +819,9 @@ everything else is autogenerated by the framework.
|
||||

|
||||
|
||||
**Applicability:** Use the Naked Objects pattern when
|
||||
* You are prototyping and need fast development cycle
|
||||
* An autogenerated user interface is good enough
|
||||
* You want to automatically publish the domain as REST services
|
||||
* you are prototyping and need fast development cycle
|
||||
* an autogenerated user interface is good enough
|
||||
* you want to automatically publish the domain as REST services
|
||||
|
||||
**Real world examples:**
|
||||
* [Apache Isis](https://isis.apache.org/)
|
||||
@ -866,11 +880,11 @@ degrading execution efficiency.
|
||||

|
||||
|
||||
**Applicability:** Use Half-Sync/Half-Async pattern when
|
||||
* A system possesses following characteristics:
|
||||
* System must perform tasks in response to external events that occur asynchronously, like hardware interrupts in OS
|
||||
* It is inefficient to dedicate separate thread of control to perform synchronous I/O for each external source of event
|
||||
* The higher level tasks in the system can be simplified significantly if I/O is performed synchronously.
|
||||
* One or more tasks in a system must run in a single thread of control, while other tasks may benefit from multi-threading.
|
||||
* a system possesses following characteristics:
|
||||
* the system must perform tasks in response to external events that occur asynchronously, like hardware interrupts in OS
|
||||
* it is inefficient to dedicate separate thread of control to perform synchronous I/O for each external source of event
|
||||
* the higher level tasks in the system can be simplified significantly if I/O is performed synchronously.
|
||||
* one or more tasks in a system must run in a single thread of control, while other tasks may benefit from multi-threading.
|
||||
|
||||
**Real world examples:**
|
||||
* [BSD Unix networking subsystem](http://www.cs.wustl.edu/~schmidt/PDF/PLoP-95.pdf)
|
||||
@ -941,9 +955,13 @@ Flyweight.
|
||||
|
||||
**To work on a new pattern** you need to do the following steps:
|
||||
|
||||
1. If there is no issue for the new pattern yet, raise new issue. Comment on the issue that you are working on it so that others don't start work on the same thing.
|
||||
1. If there is no issue for the new pattern yet, raise new issue. Comment on
|
||||
the issue that you are working on it so that others don't start work on the
|
||||
same thing.
|
||||
2. Fork the repository.
|
||||
3. Implement the code changes in your fork. Remember to add sufficient comments documenting the implementation. Reference the issue id e.g. #52 in your commit messages.
|
||||
3. Implement the code changes in your fork. Remember to add sufficient comments
|
||||
documenting the implementation. Reference the issue id e.g. #52 in your
|
||||
commit messages.
|
||||
4. Create a simple class diagram from your example code.
|
||||
5. Add description of the pattern in README.md and link to the class diagram.
|
||||
6. Create a pull request.
|
||||
@ -953,7 +971,9 @@ Flyweight.
|
||||
1. Check that the issue has "help wanted" badge
|
||||
2. Comment on the issue that you are working on it
|
||||
3. Fork the repository.
|
||||
4. Implement the code changes in your fork. Remember to add sufficient comments documenting the implementation. Reference the issue id e.g. #52 in your commit messages.
|
||||
4. Implement the code changes in your fork. Remember to add sufficient comments
|
||||
documenting the implementation. Reference the issue id e.g. #52 in your
|
||||
commit messages.
|
||||
5. Create a pull request.
|
||||
|
||||
**For creating/editing UML diagrams** you need [ObjectAid UML Explorer for Eclipse](http://www.objectaid.com/home).
|
||||
@ -997,6 +1017,7 @@ other words, version numbers are used only for project planning sake.
|
||||
* [Patterns of Enterprise Application Architecture](http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420)
|
||||
* [Spring Data](http://www.amazon.com/Spring-Data-Mark-Pollack/dp/1449323952/ref=sr_1_1)
|
||||
* [J2EE Design Patterns](http://www.amazon.com/J2EE-Design-Patterns-William-Crawford/dp/0596004273/ref=sr_1_2)
|
||||
* [Marco Castigliego - Step Builder](http://rdafbn.blogspot.co.uk/2012/07/step-builder-pattern_28.html)
|
||||
|
||||
|
||||
# License
|
||||
|
1
pom.xml
1
pom.xml
@ -73,6 +73,7 @@
|
||||
<module>async-method-invocation</module>
|
||||
<module>business-delegate</module>
|
||||
<module>half-sync-half-async</module>
|
||||
<module>step-builder</module>
|
||||
<module>layers</module>
|
||||
</modules>
|
||||
|
||||
|
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 ");
|
||||
sb.append(name);
|
||||
sb.append(" armed with a ");
|
||||
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);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user