Skip to content

Commit d57da25

Browse files
committed
added Property pattern
1 parent eddf2e6 commit d57da25

File tree

10 files changed

+303
-3
lines changed

10 files changed

+303
-3
lines changed

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ Creational design patterns abstract the instantiation process. They help make a
1515
* [Builder](#builder)
1616
* [Factory Method](#factory-method)
1717
* [Prototype](#prototype)
18+
* [Property](#property)
1819
* [Singleton](#singleton)
19-
20+
2021
### Structural Patterns
2122

2223
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
433434
**Applicability:** Use the Execute Around idiom when
434435
* You use an API that requires methods to be called in pairs such as open/close or allocate/deallocate.
435436

437+
## <a name="property">Property</a> [&#8593;](#list-of-design-patterns)
438+
**Intent:** Create hierarchy of objects and new objects using already existing objects as parents.
439+
440+
![alt text](https://github.com/iluwatar/java-design-patterns/blob/master/property/etc/property.jpg "Property")
441+
442+
**Applicability:** Use the Property pattern when
443+
* when you like to have objects with dynamic set of fields and prototype inheritance
444+
445+
**Real world examples:**
446+
* [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain) prototype inheritance
447+
436448
# Frequently asked questions
437449

438450
**<a id="Q1">Q: What is the difference between State and Strategy patterns?</a>**

pom.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@
4141
<module>null-object</module>
4242
<module>event-aggregator</module>
4343
<module>callback</module>
44-
<module>execute-around</module>
45-
</modules>
44+
<module>execute-around</module>
45+
<module>property</module>
46+
</modules>
4647

4748
<dependencyManagement>
4849
<dependencies>

property/etc/property.jpg

44.8 KB
Loading

property/etc/property.ucls

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<class-diagram version="1.1.8" icons="true" automaticImage="JPEG" always-add-relationships="false"
3+
generalizations="true" realizations="true" associations="true" dependencies="false" nesting-relationships="true">
4+
<class id="1" language="java" name="com.iluwatar.Character" project="property"
5+
file="/property/src/main/java/com/iluwatar/Character.java" binary="false" corner="BOTTOM_RIGHT">
6+
<position height="-1" width="-1" x="497" y="232"/>
7+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
8+
sort-features="false" accessors="true" visibility="true">
9+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
10+
<operations public="true" package="true" protected="true" private="true" static="true"/>
11+
</display>
12+
</class>
13+
<enumeration id="2" language="java" name="com.iluwatar.Character.Type" project="property"
14+
file="/property/src/main/java/com/iluwatar/Character.java" binary="false" corner="BOTTOM_RIGHT">
15+
<position height="-1" width="-1" x="320" y="231"/>
16+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
17+
sort-features="false" accessors="true" visibility="true">
18+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
19+
<operations public="true" package="true" protected="true" private="true" static="true"/>
20+
</display>
21+
</enumeration>
22+
<enumeration id="3" language="java" name="com.iluwatar.Stats" project="property"
23+
file="/property/src/main/java/com/iluwatar/Stats.java" binary="false" corner="BOTTOM_RIGHT">
24+
<position height="-1" width="-1" x="695" y="205"/>
25+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
26+
sort-features="false" accessors="true" visibility="true">
27+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
28+
<operations public="true" package="true" protected="true" private="true" static="true"/>
29+
</display>
30+
</enumeration>
31+
<interface id="4" language="java" name="com.iluwatar.Prototype" project="property"
32+
file="/property/src/main/java/com/iluwatar/Prototype.java" binary="false" corner="BOTTOM_RIGHT">
33+
<position height="-1" width="-1" x="495" y="487"/>
34+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
35+
sort-features="false" accessors="true" visibility="true">
36+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
37+
<operations public="true" package="true" protected="true" private="true" static="true"/>
38+
</display>
39+
</interface>
40+
<association id="5">
41+
<end type="SOURCE" refId="1" navigable="false">
42+
<attribute id="6" name="type"/>
43+
<multiplicity id="7" minimum="0" maximum="1"/>
44+
</end>
45+
<end type="TARGET" refId="2" navigable="true"/>
46+
<display labels="true" multiplicity="true"/>
47+
</association>
48+
<association id="8">
49+
<end type="SOURCE" refId="1" navigable="false">
50+
<attribute id="9" name="prototype"/>
51+
<multiplicity id="10" minimum="0" maximum="1"/>
52+
</end>
53+
<end type="TARGET" refId="4" navigable="true"/>
54+
<display labels="true" multiplicity="true"/>
55+
</association>
56+
<nesting id="11">
57+
<end type="SOURCE" refId="1"/>
58+
<end type="TARGET" refId="2"/>
59+
</nesting>
60+
<realization id="12">
61+
<end type="SOURCE" refId="1"/>
62+
<end type="TARGET" refId="4"/>
63+
</realization>
64+
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
65+
sort-features="false" accessors="true" visibility="true">
66+
<attributes public="true" package="true" protected="true" private="true" static="true"/>
67+
<operations public="true" package="true" protected="true" private="true" static="true"/>
68+
</classifier-display>
69+
<association-display labels="true" multiplicity="true"/>
70+
</class-diagram>

property/pom.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0"?>
2+
<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"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>com.iluwatar</groupId>
7+
<artifactId>java-design-patterns</artifactId>
8+
<version>1.0-SNAPSHOT</version>
9+
</parent>
10+
<artifactId>property</artifactId>
11+
<dependencies>
12+
<dependency>
13+
<groupId>junit</groupId>
14+
<artifactId>junit</artifactId>
15+
<scope>test</scope>
16+
</dependency>
17+
</dependencies>
18+
</project>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.iluwatar;
2+
3+
import com.iluwatar.Character.Type;
4+
5+
/**
6+
* Example of Character instantiation using Property pattern (as concept also known like Prototype inheritance).
7+
* In prototype inheritance instead of classes, as opposite to Java class inheritance,
8+
* objects are used to create another objects and object hierarchies.
9+
* Hierarchies are created using prototype chain through delegation: every object has link to parent object.
10+
* 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.
11+
*/
12+
public class App {
13+
14+
public static void main(String[] args) {
15+
/* set up */
16+
Prototype charProto = new Character();
17+
charProto.set(Stats.STRENGTH, 10);
18+
charProto.set(Stats.AGILITY, 10);
19+
charProto.set(Stats.ARMOR, 10);
20+
charProto.set(Stats.ATTACK_POWER, 10);
21+
22+
Character mageProto = new Character(Type.MAGE, charProto);
23+
mageProto.set(Stats.INTELLECT, 15);
24+
mageProto.set(Stats.SPIRIT, 10);
25+
26+
Character warProto = new Character(Type.WARRIOR, charProto);
27+
warProto.set(Stats.RAGE, 15);
28+
warProto.set(Stats.ARMOR, 15); // boost default armor for warrior
29+
30+
Character rogueProto = new Character(Type.ROGUE, charProto);
31+
rogueProto.set(Stats.ENERGY, 15);
32+
rogueProto.set(Stats.AGILITY, 15); // boost default agility for rogue
33+
34+
/* usage */
35+
Character mag = new Character("Player_1", mageProto);
36+
mag.set(Stats.ARMOR, 8);
37+
System.out.println(mag);
38+
39+
Character warrior = new Character("Player_2", warProto);
40+
System.out.println(warrior);
41+
42+
Character rogue = new Character("Player_3", rogueProto);
43+
System.out.println(rogue);
44+
45+
Character rogueDouble = new Character("Player_4", rogue);
46+
rogueDouble.set(Stats.ATTACK_POWER, 12);
47+
System.out.println(rogueDouble);
48+
}
49+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package com.iluwatar;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
/**
7+
* Represents Character in game and his abilities (base stats).
8+
*/
9+
public class Character implements Prototype {
10+
11+
public enum Type {
12+
WARRIOR, MAGE, ROGUE
13+
}
14+
15+
private final Prototype prototype;
16+
private final Map<Stats, Integer> properties = new HashMap<>();
17+
18+
private String name;
19+
private Type type;
20+
21+
public Character() {
22+
this.prototype = new Prototype() { // Null-value object
23+
@Override
24+
public Integer get(Stats stat) {
25+
return null;
26+
}
27+
@Override
28+
public boolean has(Stats stat) {
29+
return false;
30+
}
31+
@Override
32+
public void set(Stats stat, Integer val) {
33+
}
34+
@Override
35+
public void remove(Stats stat) {
36+
}}
37+
;
38+
}
39+
40+
public Character(Type type, Prototype prototype) {
41+
this.type = type;
42+
this.prototype = prototype;
43+
}
44+
45+
public Character(String name, Character prototype) {
46+
this.name = name;
47+
this.type = prototype.type;
48+
this.prototype = prototype;
49+
}
50+
51+
public String name() {
52+
return name;
53+
}
54+
55+
public Type type() {
56+
return type;
57+
}
58+
59+
@Override
60+
public Integer get(Stats stat) {
61+
boolean containsValue = properties.containsKey(stat);
62+
if (containsValue) {
63+
return properties.get(stat);
64+
} else {
65+
return prototype.get(stat);
66+
}
67+
}
68+
69+
@Override
70+
public boolean has(Stats stat) {
71+
return get(stat) != null;
72+
}
73+
74+
@Override
75+
public void set(Stats stat, Integer val) {
76+
properties.put(stat, val);
77+
}
78+
79+
@Override
80+
public void remove(Stats stat) {
81+
properties.put(stat, null);
82+
}
83+
84+
@Override
85+
public String toString() {
86+
StringBuilder builder = new StringBuilder();
87+
if (name != null) {
88+
builder
89+
.append("Player: ")
90+
.append(name)
91+
.append("\n");
92+
}
93+
94+
if (type != null) {
95+
builder
96+
.append("Character type: ")
97+
.append(type.name())
98+
.append("\n");
99+
}
100+
101+
builder.append("Stats:\n");
102+
for (Stats stat : Stats.values()) {
103+
Integer value = this.get(stat);
104+
if (value == null) {
105+
continue;
106+
}
107+
builder
108+
.append(" - ")
109+
.append(stat.name())
110+
.append(":")
111+
.append(value)
112+
.append("\n");
113+
}
114+
return builder.toString();
115+
}
116+
117+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.iluwatar;
2+
3+
/**
4+
* Interface for prototype inheritance
5+
*/
6+
public interface Prototype {
7+
8+
public Integer get(Stats stat);
9+
public boolean has(Stats stat);
10+
public void set(Stats stat, Integer val);
11+
public void remove(Stats stat);
12+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.iluwatar;
2+
3+
/**
4+
* All possible attributes that Character can have
5+
*/
6+
public enum Stats {
7+
8+
AGILITY, STRENGTH, ATTACK_POWER, ARMOR, INTELLECT, SPIRIT, ENERGY, RAGE
9+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.iluwatar;
2+
3+
import org.junit.Test;
4+
5+
public class AppTest {
6+
7+
@Test
8+
public void test() {
9+
String[] args = {};
10+
App.main(args);
11+
}
12+
}

0 commit comments

Comments
 (0)