@@ -17,17 +17,17 @@ copying this prototype.
17
17
18
18
##Explanation
19
19
20
- First it should be noted that Prototype pattern is not used to gain performance benefits. It's only
21
- used for creating new objects from prototypeinstance .
20
+ First, it should be noted that the Prototype pattern is not used to gain performance benefits. It's only
21
+ used for creating new objects from prototypeinstances .
22
22
23
- Real world example
23
+ Real- world example
24
24
25
25
> Remember Dolly? The sheep that was cloned! Lets not get into the details but the key point here is
26
26
> that it is all about cloning.
27
27
28
28
In plain words
29
29
30
- > Create object based on an existing object through cloning.
30
+ > Createan object based on an existing object through cloning.
31
31
32
32
Wikipedia says
33
33
@@ -40,35 +40,127 @@ of going through the trouble of creating an object from scratch and setting it u
40
40
41
41
** Programmatic Example**
42
42
43
- In Java, it can be easily done by implementing` Cloneable ` and overriding` clone ` from` Object `
43
+ In Java, the prototype pattern is recommended to be implemented as follows. First, create an
44
+ interface with a method for cloning objects. In this example,` Prototype ` interface accomplishes
45
+ this with its` copy ` method.
44
46
45
47
``` java
46
- class Sheep implements Cloneable {
47
- private String name;
48
- public Sheep (String name ) {this . name= name; }
49
- public void setName (String name ) {this . name= name; }
50
- public String getName () {return name; }
48
+ public interface Prototype {
49
+ Object copy ();
50
+ }
51
+ ```
52
+
53
+ Our example contains a hierarchy of different creatures. For example, let's look at` Beast ` and
54
+ ` OrcBeast ` classes.
55
+
56
+ ``` java
57
+ @EqualsAndHashCode
58
+ @NoArgsConstructor
59
+ public abstract class Beast implements Prototype {
60
+
61
+ public Beast (Beast source ) {
62
+ }
63
+
64
+ @Override
65
+ public abstract Beast copy ();
66
+ }
67
+
68
+ @EqualsAndHashCode (callSuper = false )
69
+ @RequiredArgsConstructor
70
+ public class OrcBeast extends Beast {
71
+
72
+ private final String weapon;
73
+
74
+ public OrcBeast (OrcBeast orcBeast ) {
75
+ super (orcBeast);
76
+ this . weapon= orcBeast. weapon;
77
+ }
78
+
79
+ @Override
80
+ public OrcBeast copy () {
81
+ return new OrcBeast (this );
82
+ }
83
+
51
84
@Override
52
- public Sheep clone () {
53
- try {
54
- return (Sheep )super . clone();
55
- }catch (CloneNotSuportedException ) {
56
- throw new InternalError ();
57
- }
85
+ public String toString () {
86
+ return " Orcish wolf attacks with" + weapon;
58
87
}
59
88
}
60
89
```
61
90
62
- Then it can be cloned like below:
91
+ We don't want to go into too much details, but the full example contains also base classes` Mage `
92
+ and` Warlord ` and there are specialized implementations for those for elves in addition to orcs.
93
+
94
+ To take full advantage of the prototype pattern, we create` HeroFactory ` and` HeroFactoryImpl `
95
+ classes to produce different kinds of creatures from prototypes.
96
+
97
+ ``` java
98
+ public interface HeroFactory {
99
+
100
+ Mage createMage ();
101
+ Warlord createWarlord ();
102
+ Beast createBeast ();
103
+ }
104
+
105
+ @RequiredArgsConstructor
106
+ public class HeroFactoryImpl implements HeroFactory {
107
+
108
+ private final Mage mage;
109
+ private final Warlord warlord;
110
+ private final Beast beast;
111
+
112
+ public Mage createMage () {
113
+ return mage. copy();
114
+ }
115
+
116
+ public Warlord createWarlord () {
117
+ return warlord. copy();
118
+ }
119
+
120
+ public Beast createBeast () {
121
+ return beast. copy();
122
+ }
123
+ }
124
+ ```
125
+
126
+ Now, we are able to show the full prototype pattern in action producing new creatures by cloning
127
+ existing instances.
63
128
64
129
``` java
65
- var original= new Sheep (" Jolly" );
66
- System . out. println(original. getName());// Jolly
130
+ var factory= new HeroFactoryImpl (
131
+ new ElfMage (" cooking" ),
132
+ new ElfWarlord (" cleaning" ),
133
+ new ElfBeast (" protecting" )
134
+ );
135
+ var mage= factory. createMage();
136
+ var warlord= factory. createWarlord();
137
+ var beast= factory. createBeast();
138
+ LOGGER . info(mage. toString());
139
+ LOGGER . info(warlord. toString());
140
+ LOGGER . info(beast. toString());
141
+
142
+ factory= new HeroFactoryImpl (
143
+ new OrcMage (" axe" ),
144
+ new OrcWarlord (" sword" ),
145
+ new OrcBeast (" laser" )
146
+ );
147
+ mage= factory. createMage();
148
+ warlord= factory. createWarlord();
149
+ beast= factory. createBeast();
150
+ LOGGER . info(mage. toString());
151
+ LOGGER . info(warlord. toString());
152
+ LOGGER . info(beast. toString());
153
+ ```
67
154
68
- // Clone and modify what is required
69
- var cloned= original. clone();
70
- cloned. setName(" Dolly" );
71
- System . out. println(cloned. getName());// Dolly
155
+ Here's the console output from running the example.
156
+
157
+ ```
158
+ Elven mage helps in cooking
159
+ Elven warlord helps in cleaning
160
+ Elven eagle helps in protecting
161
+ Orcish mage attacks with axe
162
+ Orcish warlord attacks with sword
163
+ Orcish wolf attacks with laser
72
164
```
73
165
74
166
##Class diagram
@@ -87,7 +179,7 @@ more convenient to install a corresponding number of prototypes and clone them r
87
179
instantiating the class manually, each time with the appropriate state.
88
180
* When object creation is expensive compared to cloning.
89
181
90
- ##Real world examples
182
+ ##Known uses
91
183
92
184
* [ java.lang.Object#clone()] ( http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#clone%28%29 )
93
185