From d57da2593bee83b5a4ec39d39c86613bb264c51d Mon Sep 17 00:00:00 2001 From: vehpsr Date: Sun, 29 Mar 2015 23:03:06 +0300 Subject: [PATCH] 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. +## Property [↑](#list-of-design-patterns) +**Intent:** Create hierarchy of objects and new objects using already existing objects as parents. + +![alt text](https://github.com/iluwatar/java-design-patterns/blob/master/property/etc/property.jpg "Property") + +**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 **Q: What is the difference between State and Strategy patterns?** diff --git a/pom.xml b/pom.xml index 5c15fe5f1..72c37c3ed 100644 --- a/pom.xml +++ b/pom.xml @@ -41,8 +41,9 @@ null-object event-aggregator callback - execute-around - + execute-around + property + 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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 v3ZEy1duew75k>#MgslGu65Eh($gU4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 @@ + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.0-SNAPSHOT + + property + + + junit + junit + test + + + 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 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); + } +}