// Abstract Factory might store a set of Prototypes from which to clone and // return product objects. [GOF, p126] public class FactoryProto { interface Xyz { Xyz cloan(); } static class Tom implements Xyz { public Xyz cloan() { return new Tom(); } public String toString() { return "ttt"; } } static class Dick implements Xyz { public Xyz cloan() { return new Dick(); } public String toString() { return "ddd"; } } static class Harry implements Xyz { public Xyz cloan() { return new Harry(); } public String toString() { return "hhh"; } } static class Factory { private static java.util.Map prototypes = new java.util.HashMap(); static { prototypes.put( "tom", new Tom() ); prototypes.put( "dick", new Dick() ); prototypes.put( "harry", new Harry() ); } public static Xyz makeObject( String s ) { return ((Xyz)prototypes.get(s)).cloan(); } } public static void main( String[] args ) { for (int i=0; i < args.length; i++) System.out.print( Factory.makeObject( args[i] ) + " " ); }} // D:\Java\patterns> java FactoryProto tom dick tom harry tom // ttt ddd ttt hhh ttt // Purpose. Prototype design pattern // 1. Create a "contract" with clone() and getName() entries // 2. Design a "registry" that maintains a cache of prototypical objects // 3. Populate the registry with an initializePrototypes() function // 4. The registry has a findAndClone() "virtual constructor" that can transform // a String into its correct object (it calls clone() which then calls "new") // 5. All classes relate themselves to the clone() contract // 6. Client uses the findAndClone() virtual ctor instead of the "new" operator interface Prototype { Object clone(); String getName(); } // 1. The clone() interface Command { void execute(); } // contract class PrototypesModule { // 2. "registry" of prototypical objs private static Prototype[] prototypes = new Prototype[9]; private static int total = 0; public static void addPrototype( Prototype obj ) { prototypes[total++] = obj; } public static Object findAndClone( String name ) { // 4. The "virtual ctor" for (int i=0; i < total; i++) if (prototypes[i].getName().equals( name )) return prototypes[i].clone(); System.out.println( name + " not found" ); return null; } } // 5. Sign-up for the clone() class This implements Prototype, Command { // contract. Each class public Object clone() { return new This(); } // calls "new" on itself public String getName() { return "This"; } // FOR the client. public void execute() { System.out.println( "This: execute" ); } } class That implements Prototype, Command { public Object clone() { return new That(); } public String getName() { return "That"; } public void execute() { System.out.println( "That: execute" ); } } class TheOther implements Prototype, Command { public Object clone() { return new TheOther(); } public String getName() { return "TheOther"; } public void execute() { System.out.println( "TheOther: execute" ); } } public class PrototypeDemo { public static void initializePrototypes() { // 3. Populate the "registry" PrototypesModule.addPrototype( new This() ); PrototypesModule.addPrototype( new That() ); PrototypesModule.addPrototype( new TheOther() ); } public static void main( String[] args ) { initializePrototypes(); Object[] objects = new Object[9]; int total = 0; for (int i=0; i < args.length; i++) { // 6. Client does not use "new" objects[total] = PrototypesModule.findAndClone( args[i] ); if (objects[total] != null) total++; } for (int i=0; i < total; i++) ((Command)objects[i]).execute(); } } // C:> java PrototypeDemo Garbage This That Nothing TheOther // Garbage not found // Nothing not found // This: execute // That: execute // TheOther: execute