From 9312059f191f3124cda755cb8959e7344ea7ecc8 Mon Sep 17 00:00:00 2001 From: vehpsr <vehpsrr@i.ua> Date: Fri, 27 Mar 2015 11:13:29 +0200 Subject: [PATCH 1/9] Callback pattern description amendment --- callback/src/main/java/com/iluwatar/App.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/callback/src/main/java/com/iluwatar/App.java b/callback/src/main/java/com/iluwatar/App.java index 6a36d66d7..2d79d8edf 100644 --- a/callback/src/main/java/com/iluwatar/App.java +++ b/callback/src/main/java/com/iluwatar/App.java @@ -1,7 +1,7 @@ package com.iluwatar; /** - * Callback pattern is more native for dynamic languages where function are first-class citizen. + * Callback pattern is more native for functional languages where function is treated as first-class citizen. * Prior to Java8 can be simulated using simple (alike command) interfaces. */ public class App { From 15adc6751ecdbad1b26d3620a153d3a943f59fdd Mon Sep 17 00:00:00 2001 From: vehpsr <vehpsrr@i.ua> Date: Fri, 27 Mar 2015 17:38:10 +0200 Subject: [PATCH 2/9] Callback pattern: added real world example --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 24735a590..4a7991277 100644 --- a/README.md +++ b/README.md @@ -421,6 +421,8 @@ Behavioral patterns are concerned with algorithms and the assignment of responsi **Applicability:** Use the Callback pattern when * 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. # Frequently asked questions From 027fd9934bac455a0e7d61410bfab791cea6bc22 Mon Sep 17 00:00:00 2001 From: Ilkka Seppala <iluwatar@gmail.com> Date: Sun, 29 Mar 2015 21:25:13 +0300 Subject: [PATCH 3/9] Added example code for Execute Around idiom. --- execute-around/pom.xml | 18 +++++++++++ .../src/main/java/com/iluwatar/App.java | 30 +++++++++++++++++++ .../java/com/iluwatar/FileWriterAction.java | 15 ++++++++++ .../java/com/iluwatar/SimpleFileWriter.java | 23 ++++++++++++++ .../src/test/java/com/iluwatar/AppTest.java | 19 ++++++++++++ pom.xml | 1 + 6 files changed, 106 insertions(+) create mode 100644 execute-around/pom.xml create mode 100644 execute-around/src/main/java/com/iluwatar/App.java create mode 100644 execute-around/src/main/java/com/iluwatar/FileWriterAction.java create mode 100644 execute-around/src/main/java/com/iluwatar/SimpleFileWriter.java create mode 100644 execute-around/src/test/java/com/iluwatar/AppTest.java diff --git a/execute-around/pom.xml b/execute-around/pom.xml new file mode 100644 index 000000000..8d8862063 --- /dev/null +++ b/execute-around/pom.xml @@ -0,0 +1,18 @@ +<?xml version="1.0"?> +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.iluwatar</groupId> + <artifactId>java-design-patterns</artifactId> + <version>1.0-SNAPSHOT</version> + </parent> + <artifactId>execute-around</artifactId> + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + </dependencies> +</project> diff --git a/execute-around/src/main/java/com/iluwatar/App.java b/execute-around/src/main/java/com/iluwatar/App.java new file mode 100644 index 000000000..d3db00045 --- /dev/null +++ b/execute-around/src/main/java/com/iluwatar/App.java @@ -0,0 +1,30 @@ +package com.iluwatar; + +import java.io.FileWriter; +import java.io.IOException; + +/** + * The Execute Around idiom specifies some code to be executed before and after + * a method. Typically the idiom is used when the API has methods to be executed in + * pairs, such as resource allocation/deallocation or lock acquisition/release. + * + * In this example, we have SimpleFileWriter class that opens and closes the file + * for the user. The user specifies only what to do with the file by providing the + * FileWriterAction implementation. + * + */ +public class App { + + public static void main( String[] args ) throws IOException { + + new SimpleFileWriter("testfile.txt", new FileWriterAction() { + + @Override + public void writeFile(FileWriter writer) throws IOException { + writer.write("Hello"); + writer.append(" "); + writer.append("there!"); + } + }); + } +} diff --git a/execute-around/src/main/java/com/iluwatar/FileWriterAction.java b/execute-around/src/main/java/com/iluwatar/FileWriterAction.java new file mode 100644 index 000000000..3f4fcd16c --- /dev/null +++ b/execute-around/src/main/java/com/iluwatar/FileWriterAction.java @@ -0,0 +1,15 @@ +package com.iluwatar; + +import java.io.FileWriter; +import java.io.IOException; + +/** + * + * Interface for specifying what to do with the file resource. + * + */ +public interface FileWriterAction { + + void writeFile(FileWriter writer) throws IOException; + +} diff --git a/execute-around/src/main/java/com/iluwatar/SimpleFileWriter.java b/execute-around/src/main/java/com/iluwatar/SimpleFileWriter.java new file mode 100644 index 000000000..c4be8a9fa --- /dev/null +++ b/execute-around/src/main/java/com/iluwatar/SimpleFileWriter.java @@ -0,0 +1,23 @@ +package com.iluwatar; + +import java.io.FileWriter; +import java.io.IOException; + +/** + * + * SimpleFileWriter handles opening and closing file for the user. The user + * only has to specify what to do with the file resource through FileWriterAction + * parameter. + * + */ +public class SimpleFileWriter { + + public SimpleFileWriter(String filename, FileWriterAction action) throws IOException { + FileWriter writer = new FileWriter(filename); + try { + action.writeFile(writer); + } finally { + writer.close(); + } + } +} diff --git a/execute-around/src/test/java/com/iluwatar/AppTest.java b/execute-around/src/test/java/com/iluwatar/AppTest.java new file mode 100644 index 000000000..3f256e7aa --- /dev/null +++ b/execute-around/src/test/java/com/iluwatar/AppTest.java @@ -0,0 +1,19 @@ +package com.iluwatar; + +import java.io.IOException; + +import org.junit.Test; + +/** + * + * Tests execute-around example. + * + */ +public class AppTest { + + @Test + public void test() throws IOException { + String[] args = {}; + App.main(args); + } +} diff --git a/pom.xml b/pom.xml index 7cfff29c4..5c15fe5f1 100644 --- a/pom.xml +++ b/pom.xml @@ -41,6 +41,7 @@ <module>null-object</module> <module>event-aggregator</module> <module>callback</module> + <module>execute-around</module> </modules> <dependencyManagement> From 12bc65adc0cc17975ce4440beeba7e8dafc9fdec Mon Sep 17 00:00:00 2001 From: Ilkka Seppala <iluwatar@gmail.com> Date: Sun, 29 Mar 2015 21:26:18 +0300 Subject: [PATCH 4/9] Added class diagram for Execute Around idiom. --- execute-around/execute-around.png | Bin 0 -> 4588 bytes execute-around/execute-around.ucls | 28 ++++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 execute-around/execute-around.png create mode 100644 execute-around/execute-around.ucls diff --git a/execute-around/execute-around.png b/execute-around/execute-around.png new file mode 100644 index 0000000000000000000000000000000000000000..fc048919d10e1c024c38dc2ad93d95cba20b9a59 GIT binary patch literal 4588 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 F{sUz;<dFaX literal 0 HcmV?d00001 diff --git a/execute-around/execute-around.ucls b/execute-around/execute-around.ucls new file mode 100644 index 000000000..680334e9b --- /dev/null +++ b/execute-around/execute-around.ucls @@ -0,0 +1,28 @@ +<?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="false" nesting-relationships="true"> + <class id="1" language="java" name="com.iluwatar.SimpleFileWriter" project="execute-around" + file="/execute-around/src/main/java/com/iluwatar/SimpleFileWriter.java" binary="false" corner="BOTTOM_RIGHT"> + <position height="88" width="261" x="213" y="298"/> + <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="2" language="java" name="com.iluwatar.FileWriterAction" project="execute-around" + file="/execute-around/src/main/java/com/iluwatar/FileWriterAction.java" binary="false" corner="BOTTOM_RIGHT"> + <position height="88" width="164" x="514" y="298"/> + <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> + <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> \ No newline at end of file From 36482d5b7ce0941cee6aabd96f35c5d4f5537a05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= <iluwatar@gmail.com> Date: Sun, 29 Mar 2015 21:41:41 +0300 Subject: [PATCH 5/9] Added description for Execute Around. --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 24735a590..13343121b 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,7 @@ Behavioral patterns are concerned with algorithms and the assignment of responsi * [Double Checked Locking](#double-checked-locking) * [Null Object](#null-object) * [Callback](#callback) +* [Execute Around](#execute-around) ## <a name="abstract-factory">Abstract Factory</a> [↑](#list-of-design-patterns) **Intent:** Provide an interface for creating families of related or dependent objects without specifying their concrete classes. @@ -421,6 +422,14 @@ Behavioral patterns are concerned with algorithms and the assignment of responsi **Applicability:** Use the Callback pattern when * When some arbitrary synchronous or asynchronous action must be performed after execution of some defined activity. +## <a name="execute-around">Execute Around</a> [↑](#list-of-design-patterns) +**Intent:** Execute Around idiom frees the user from certain actions that should always be executed before and after the business method. A good example of this is resource allocation and deallocation leaving the user to specify 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. + # Frequently asked questions From 1fc15829ade98732e0debdf816896a5b9b66516b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= <iluwatar@gmail.com> Date: Sun, 29 Mar 2015 21:44:05 +0300 Subject: [PATCH 6/9] Fixed link. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 13343121b..bad1ec15e 100644 --- a/README.md +++ b/README.md @@ -425,7 +425,7 @@ Behavioral patterns are concerned with algorithms and the assignment of responsi ## <a name="execute-around">Execute Around</a> [↑](#list-of-design-patterns) **Intent:** Execute Around idiom frees the user from certain actions that should always be executed before and after the business method. A good example of this is resource allocation and deallocation leaving the user to specify 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. From 911a3505b2d648dd92eddd404a5a97a1b3a8a577 Mon Sep 17 00:00:00 2001 From: Ilkka Seppala <iluwatar@gmail.com> Date: Sun, 29 Mar 2015 22:03:07 +0300 Subject: [PATCH 7/9] Added book reference. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index bad1ec15e..325f42b27 100644 --- a/README.md +++ b/README.md @@ -475,6 +475,7 @@ The difference is the intent of the patterns. While Proxy controls access to the * [Let’s Modify the Objects-First Approach into Design-Patterns-First](http://edu.pecinovsky.cz/papers/2006_ITiCSE_Design_Patterns_First.pdf) * [Pattern Languages of Program Design](http://www.amazon.com/Pattern-Languages-Program-Design-Coplien/dp/0201607344/ref=sr_1_1) * [Martin Fowler - Event Aggregator](http://martinfowler.com/eaaDev/EventAggregator.html) +* [Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions](http://www.amazon.com/Functional-Programming-Java-Harnessing-Expressions/dp/1937785467/ref=sr_1_1) From d57da2593bee83b5a4ec39d39c86613bb264c51d Mon Sep 17 00:00:00 2001 From: vehpsr <vehpsrr@gmail.com> Date: Sun, 29 Mar 2015 23:03:06 +0300 Subject: [PATCH 8/9] added Property pattern --- README.md | 14 ++- pom.xml | 5 +- property/etc/property.jpg | Bin 0 -> 45915 bytes property/etc/property.ucls | 70 +++++++++++ property/pom.xml | 18 +++ property/src/main/java/com/iluwatar/App.java | 49 ++++++++ .../src/main/java/com/iluwatar/Character.java | 117 ++++++++++++++++++ .../src/main/java/com/iluwatar/Prototype.java | 12 ++ .../src/main/java/com/iluwatar/Stats.java | 9 ++ .../src/test/java/com/iluwatar/AppTest.java | 12 ++ 10 files changed, 303 insertions(+), 3 deletions(-) create mode 100644 property/etc/property.jpg create mode 100644 property/etc/property.ucls create mode 100644 property/pom.xml create mode 100644 property/src/main/java/com/iluwatar/App.java create mode 100644 property/src/main/java/com/iluwatar/Character.java create mode 100644 property/src/main/java/com/iluwatar/Prototype.java create mode 100644 property/src/main/java/com/iluwatar/Stats.java create mode 100644 property/src/test/java/com/iluwatar/AppTest.java diff --git a/README.md b/README.md index 073cb4859..34ff788dd 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,9 @@ Creational design patterns abstract the instantiation process. They help make a * [Builder](#builder) * [Factory Method](#factory-method) * [Prototype](#prototype) +* [Property](#property) * [Singleton](#singleton) - + ### Structural Patterns Structural patterns are concerned with how classes and objects are composed to form larger structures. @@ -433,6 +434,17 @@ Behavioral patterns are concerned with algorithms and the assignment of responsi **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. +## <a name="property">Property</a> [↑](#list-of-design-patterns) +**Intent:** Create hierarchy of objects and new objects using already existing objects as parents. + + + +**Applicability:** Use the Property pattern when +* when you like to have objects with dynamic set of fields and prototype inheritance + +**Real world examples:** +* [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain) prototype inheritance + # Frequently asked questions **<a id="Q1">Q: What is the difference between State and Strategy patterns?</a>** diff --git a/pom.xml b/pom.xml index 5c15fe5f1..72c37c3ed 100644 --- a/pom.xml +++ b/pom.xml @@ -41,8 +41,9 @@ <module>null-object</module> <module>event-aggregator</module> <module>callback</module> - <module>execute-around</module> - </modules> + <module>execute-around</module> + <module>property</module> + </modules> <dependencyManagement> <dependencies> diff --git a/property/etc/property.jpg b/property/etc/property.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e3da03e0c0f135446082b5edac8dd4014126ce40 GIT binary patch literal 45915 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 literal 0 HcmV?d00001 diff --git a/property/etc/property.ucls b/property/etc/property.ucls new file mode 100644 index 000000000..0ad1d61eb --- /dev/null +++ b/property/etc/property.ucls @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8"?> +<class-diagram version="1.1.8" icons="true" automaticImage="JPEG" always-add-relationships="false" + generalizations="true" realizations="true" associations="true" dependencies="false" nesting-relationships="true"> + <class id="1" language="java" name="com.iluwatar.Character" project="property" + file="/property/src/main/java/com/iluwatar/Character.java" binary="false" corner="BOTTOM_RIGHT"> + <position height="-1" width="-1" x="497" y="232"/> + <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> + <enumeration id="2" language="java" name="com.iluwatar.Character.Type" project="property" + file="/property/src/main/java/com/iluwatar/Character.java" binary="false" corner="BOTTOM_RIGHT"> + <position height="-1" width="-1" x="320" y="231"/> + <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> + </enumeration> + <enumeration id="3" language="java" name="com.iluwatar.Stats" project="property" + file="/property/src/main/java/com/iluwatar/Stats.java" binary="false" corner="BOTTOM_RIGHT"> + <position height="-1" width="-1" x="695" y="205"/> + <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> + </enumeration> + <interface id="4" language="java" name="com.iluwatar.Prototype" project="property" + file="/property/src/main/java/com/iluwatar/Prototype.java" binary="false" corner="BOTTOM_RIGHT"> + <position height="-1" width="-1" x="495" y="487"/> + <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> + <association id="5"> + <end type="SOURCE" refId="1" navigable="false"> + <attribute id="6" name="type"/> + <multiplicity id="7" minimum="0" maximum="1"/> + </end> + <end type="TARGET" refId="2" navigable="true"/> + <display labels="true" multiplicity="true"/> + </association> + <association id="8"> + <end type="SOURCE" refId="1" navigable="false"> + <attribute id="9" name="prototype"/> + <multiplicity id="10" minimum="0" maximum="1"/> + </end> + <end type="TARGET" refId="4" navigable="true"/> + <display labels="true" multiplicity="true"/> + </association> + <nesting id="11"> + <end type="SOURCE" refId="1"/> + <end type="TARGET" refId="2"/> + </nesting> + <realization id="12"> + <end type="SOURCE" refId="1"/> + <end type="TARGET" refId="4"/> + </realization> + <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> \ No newline at end of file diff --git a/property/pom.xml b/property/pom.xml new file mode 100644 index 000000000..a26894f0a --- /dev/null +++ b/property/pom.xml @@ -0,0 +1,18 @@ +<?xml version="1.0"?> +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.iluwatar</groupId> + <artifactId>java-design-patterns</artifactId> + <version>1.0-SNAPSHOT</version> + </parent> + <artifactId>property</artifactId> + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + </dependencies> +</project> diff --git a/property/src/main/java/com/iluwatar/App.java b/property/src/main/java/com/iluwatar/App.java new file mode 100644 index 000000000..95ff4355f --- /dev/null +++ b/property/src/main/java/com/iluwatar/App.java @@ -0,0 +1,49 @@ +package com.iluwatar; + +import com.iluwatar.Character.Type; + +/** + * Example of Character instantiation using Property pattern (as concept also known like Prototype inheritance). + * In prototype inheritance instead of classes, as opposite to Java class inheritance, + * objects are used to create another objects and object hierarchies. + * Hierarchies are created using prototype chain through delegation: every object has link to parent object. + * Any base (parent) object can be amended at runtime (by adding or removal of some property), and all child objects will be affected as result. + */ +public class App { + + public static void main(String[] args) { + /* set up */ + Prototype charProto = new Character(); + charProto.set(Stats.STRENGTH, 10); + charProto.set(Stats.AGILITY, 10); + charProto.set(Stats.ARMOR, 10); + charProto.set(Stats.ATTACK_POWER, 10); + + Character mageProto = new Character(Type.MAGE, charProto); + mageProto.set(Stats.INTELLECT, 15); + mageProto.set(Stats.SPIRIT, 10); + + Character warProto = new Character(Type.WARRIOR, charProto); + warProto.set(Stats.RAGE, 15); + warProto.set(Stats.ARMOR, 15); // boost default armor for warrior + + Character rogueProto = new Character(Type.ROGUE, charProto); + rogueProto.set(Stats.ENERGY, 15); + rogueProto.set(Stats.AGILITY, 15); // boost default agility for rogue + + /* usage */ + Character mag = new Character("Player_1", mageProto); + mag.set(Stats.ARMOR, 8); + System.out.println(mag); + + Character warrior = new Character("Player_2", warProto); + System.out.println(warrior); + + Character rogue = new Character("Player_3", rogueProto); + System.out.println(rogue); + + Character rogueDouble = new Character("Player_4", rogue); + rogueDouble.set(Stats.ATTACK_POWER, 12); + System.out.println(rogueDouble); + } +} diff --git a/property/src/main/java/com/iluwatar/Character.java b/property/src/main/java/com/iluwatar/Character.java new file mode 100644 index 000000000..ac8abaa0e --- /dev/null +++ b/property/src/main/java/com/iluwatar/Character.java @@ -0,0 +1,117 @@ +package com.iluwatar; + +import java.util.HashMap; +import java.util.Map; + +/** + * Represents Character in game and his abilities (base stats). + */ +public class Character implements Prototype { + + public enum Type { + WARRIOR, MAGE, ROGUE + } + + private final Prototype prototype; + private final Map<Stats, Integer> properties = new HashMap<>(); + + private String name; + private Type type; + + public Character() { + this.prototype = new Prototype() { // Null-value object + @Override + public Integer get(Stats stat) { + return null; + } + @Override + public boolean has(Stats stat) { + return false; + } + @Override + public void set(Stats stat, Integer val) { + } + @Override + public void remove(Stats stat) { + }} + ; + } + + public Character(Type type, Prototype prototype) { + this.type = type; + this.prototype = prototype; + } + + public Character(String name, Character prototype) { + this.name = name; + this.type = prototype.type; + this.prototype = prototype; + } + + public String name() { + return name; + } + + public Type type() { + return type; + } + + @Override + public Integer get(Stats stat) { + boolean containsValue = properties.containsKey(stat); + if (containsValue) { + return properties.get(stat); + } else { + return prototype.get(stat); + } + } + + @Override + public boolean has(Stats stat) { + return get(stat) != null; + } + + @Override + public void set(Stats stat, Integer val) { + properties.put(stat, val); + } + + @Override + public void remove(Stats stat) { + properties.put(stat, null); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + if (name != null) { + builder + .append("Player: ") + .append(name) + .append("\n"); + } + + if (type != null) { + builder + .append("Character type: ") + .append(type.name()) + .append("\n"); + } + + builder.append("Stats:\n"); + for (Stats stat : Stats.values()) { + Integer value = this.get(stat); + if (value == null) { + continue; + } + builder + .append(" - ") + .append(stat.name()) + .append(":") + .append(value) + .append("\n"); + } + return builder.toString(); + } + +} diff --git a/property/src/main/java/com/iluwatar/Prototype.java b/property/src/main/java/com/iluwatar/Prototype.java new file mode 100644 index 000000000..ef9d2d7b6 --- /dev/null +++ b/property/src/main/java/com/iluwatar/Prototype.java @@ -0,0 +1,12 @@ +package com.iluwatar; + +/** + * Interface for prototype inheritance + */ +public interface Prototype { + + public Integer get(Stats stat); + public boolean has(Stats stat); + public void set(Stats stat, Integer val); + public void remove(Stats stat); +} diff --git a/property/src/main/java/com/iluwatar/Stats.java b/property/src/main/java/com/iluwatar/Stats.java new file mode 100644 index 000000000..3c5648148 --- /dev/null +++ b/property/src/main/java/com/iluwatar/Stats.java @@ -0,0 +1,9 @@ +package com.iluwatar; + +/** + * All possible attributes that Character can have + */ +public enum Stats { + + AGILITY, STRENGTH, ATTACK_POWER, ARMOR, INTELLECT, SPIRIT, ENERGY, RAGE +} diff --git a/property/src/test/java/com/iluwatar/AppTest.java b/property/src/test/java/com/iluwatar/AppTest.java new file mode 100644 index 000000000..6db5ad214 --- /dev/null +++ b/property/src/test/java/com/iluwatar/AppTest.java @@ -0,0 +1,12 @@ +package com.iluwatar; + +import org.junit.Test; + +public class AppTest { + + @Test + public void test() { + String[] args = {}; + App.main(args); + } +} From 46a6ff2894da5a9f32cf1bcb47fd93a299ce0d75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= <iluwatar@gmail.com> Date: Tue, 31 Mar 2015 19:43:35 +0300 Subject: [PATCH 9/9] Added introduction chapter to README.md. --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 34ff788dd..ca2c6fcee 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,14 @@  +## Introduction + +Design patterns are formalized best practices that the programmer can use to solve common problems when designing an application or system. + +Design patterns can speed up the development process by providing tested, proven development paradigms. + +Reusing design patterns helps to prevent subtle issues that can cause major problems, and it also improves code readability for coders and architects who are familiar with the patterns. + ## <a name="list-of-design-patterns">List of Design Patterns</a> ### Creational Patterns