Table of Contents

Prototype Pattern

https://en.wikipedia.org/wiki/Design_Patterns#Patterns_by_Type

Java

Prototype

/* 깊은 복사를 위해 Serializable 필요 */
public class Manager<T extends Serializable> {
	private HashMap<String, T> showcase = new HashMap<>();
	
	public void register(String prototypeName, T prototype) {
		showcase.put(prototypeName, prototype);
	}
	
	public T createClone(String prototypeName) {
		T target = showcase.get(prototypeName);
		
		try {
	        ByteArrayOutputStream baos = new ByteArrayOutputStream();
	        ObjectOutputStream oos = new ObjectOutputStream(baos);
	        oos.writeObject(target);
	        oos.close();
	        baos.close();
	 
	        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
	        ObjectInputStream ois = new ObjectInputStream(bais);
	        ois.close();
	        bais.close();
	        
	        return (T) ois.readObject();
	    } catch (IOException e) {
	        return null;
	    } catch (ClassNotFoundException e) {
	        return null;
	    }
	}
}

ConcretePrototype

/* 깊은 복사를 위해 Serializable 필요 */
public interface Character extends Serializable {
	void attack();
	void block();
}

public class Player implements Character {

	@Override
	public void attack() {
		System.out.println("Player - attack!");
	}

	@Override
	public void block() {
		System.out.println("Player - block!");
	}
}

public class Monster implements Character {

	@Override
	public void attack() {
		System.out.println("Monster - attack!");
	}

	@Override
	public void block() {
		System.out.println("Monster - block!");
	}
}

Client

public class Main {
	public static void main(String[] args) {
		Manager<Character> manager = new Manager<>();
		
		Player playerOriginal = new Player();
		Monster monsterOriginal = new Monster();
		
		manager.register("player", playerOriginal);
		manager.register("monster", monsterOriginal);
		
		Character playerClone = manager.createClone("player");
		Character monsterClone = manager.createClone("monster");
		
		print(playerOriginal, playerClone);
		print(monsterOriginal, monsterClone);
	}
	
	private static void print(Character original, Character clone) {
		original.attack();
		original.block();
		
		clone.attack();
		clone.block();
		
		System.out.println("같은 참조를 갖는가? " + (original == clone));
		System.out.println();
	}
}

/*
Player - attack!
Player - block!
Player - attack!
Player - block!
같은 참조를 갖는가? false

Monster - attack!
Monster - block!
Monster - attack!
Monster - block!
같은 참조를 갖는가? false
*/

C#

namespace PrototypePattern
{
    class Program
    {
        static void Main(string[] args)
        {
            Manager manager = new Manager();

            Character player = new Player();

            manager.Register("player", player);
            Character playerClone = manager.CreateClone("player");


            playerClone.attack();

            Console.WriteLine(player == playerClone);
        }
    }

    /* Client */
    public class Manager
    {
        private static Dictionary<string, Character> showcase = new Dictionary<string, Character>();

        public void Register(string key, Character prototype)
        {
            showcase.Add(key, prototype);
        }

        public Character CreateClone(string key)
        {
            using (var ms = new MemoryStream())
            {
                var formatter = new BinaryFormatter();
                formatter.Serialize(ms, showcase[key]);
                ms.Position = 0;

                return formatter.Deserialize(ms) as Character;
            }
        }
    }

    /* Prototype */
    public interface Character
    {
        void attack();
        void block();
    }

    /* ConcretePrototype */
    [Serializable]
    public class Player : Character
    {
        public void attack()
        {
            Console.WriteLine("Player - attack!");
        }

        public void block()
        {
            Console.WriteLine("Player - block!");
        }
    }

    /* ConcretePrototype */
    [Serializable]
    public class Monster : Character
    {
        public void attack()
        {
            Console.WriteLine("Monster - attack!");
        }

        public void block()
        {
            Console.WriteLine("Monster - block!");
        }
    }
}