본문 바로가기
컴퓨터 과학/디자인패턴

[디자인패턴] 생성 패턴(5) : 프로토타입(Prototype)

by webcodur 2024. 3. 24.
728x90

목차

     

     

     

    프로토타입(Prototype)

    프로토타입 디자인 패턴은 생성 디자인 패턴의 하나로, 객체를 생성하는 비용이 높을 때 원본 객체를 복제하는 방식으로 새 객체를 생성하는 기법이다. 이 패턴은 '프로토타입'이라는 용어에서 유래했다. 프로토타입(Prototype)이란 원형이나 본보기를 의미하며, 이 패턴에서는 객체의 원형(프로토타입)을 복제(clone)하여 새 객체를 생성한다.

     

    패턴 미적용 예시 코드

    C#에서 프로토타입 패턴을 적용하지 않은 경우, 객체를 생성할 때마다 새로운 인스턴스를 처음부터 생성해야 한다. 복잡한 객체의 경우 생성 과정이 비효율적이 될 수 있다.

    using System;
    
    class ComplexObject
    {
        public int Property1 { get; set; }
        public string Property2 { get; set; }
    
        public ComplexObject(int property1, string property2)
        {
            Property1 = property1;
            Property2 = property2;
        }
    
        public void Display()
        {
            Console.WriteLine($"Property1: {Property1}, Property2: {Property2}");
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            ComplexObject obj1 = new ComplexObject(1, "Object 1");
            obj1.Display();
    
            // 새 객체를 생성할 때마다 전체 생성자를 다시 호출
            ComplexObject obj2 = new ComplexObject(2, "Object 2");
            obj2.Display();
        }
    }
    

    이 코드는 객체를 생성할 때마다 모든 초기화 코드를 반복해야 하며, 객체의 생성 비용이 높거나 초기화 과정이 복잡한 경우 비효율적일 수 있다

     

    패턴 적용 예시 코드

    프로토타입 패턴을 적용하면 초기화된 객체의 복사본을 생성하여 위와 같은 비효율성을 해결할 수 있다. C#에서는 ICloneable 인터페이스를 구현하여 이를 달성할 수 있다.

    using System;
    
    class ComplexObject : ICloneable
    {
        public int Property1 { get; set; }
        public string Property2 { get; set; }
    
        public ComplexObject(int property1, string property2)
        {
            Property1 = property1;
            Property2 = property2;
        }
    
        public object Clone()
        {
            return this.MemberwiseClone(); // 얕은 복사 수행
        }
    
        public void Display()
        {
            Console.WriteLine($"Property1: {Property1}, Property2: {Property2}");
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            ComplexObject original = new ComplexObject(1, "Original");
            original.Display();
    
            // 프로토타입을 이용한 복사본 생성
            ComplexObject copy = (ComplexObject)original.Clone();
            copy.Property1 = 2;
            copy.Property2 = "Copied";
            copy.Display();
        }
    }
    

    이 예시에서는 ICloneable 인터페이스의 Clone 메서드를 구현하여 객체의 복사본을 생성한다. 이 방식은 원본 객체가 이미 초기화된 상태의 복잡한 설정을 가지고 있을 경우, 새 객체를 효율적으로 생성할 수 있는 장점이 있다. MemberwiseClone 메서드를 사용하여 얕은 복사를 수행하는데, 필요에 따라 깊은 복사를 구현할 수도 있다.

     

     

    패턴 미적용 예시 코드(2)

    실질적인 예시로, 한 게임에서 플레이어가 다양한 타입의 적을 생성해야 하는 상황을 생각해볼 수 있다. 게임에는 "Goblin", "Orc", "Troll" 등 여러 종류의 적이 있으며, 각각의 적은 공격력, 체력, 방어력 등을 가지고 있다. 프로토타입 패턴을 적용하지 않았을 때는 각 적을 생성할 때마다 그 정보를 모두 초기화해야 하지만, 프로토타입 패턴을 적용하면 초기화된 적의 프로토타입을 복제해서 새로운 적을 손쉽게 생성할 수 있다.

    using System;
    
    class Enemy
    {
        public string Type { get; set; }
        public int Health { get; set; }
        public int Attack { get; set; }
        public int Defense { get; set; }
    
        public Enemy(string type, int health, int attack, int defense)
        {
            Type = type;
            Health = health;
            Attack = attack;
            Defense = defense;
        }
    
        public void DisplayStatus()
        {
            Console.WriteLine($"{Type} - Stats:");
            Console.WriteLine($"Health: {Health}, Attack: {Attack}, Defense: {Defense}");
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Enemy goblin = new Enemy("Goblin", 100, 15, 10);
            goblin.DisplayStatus();
    
            // 새로운 Goblin을 만들기 위해 정보를 다시 입력
            Enemy anotherGoblin = new Enemy("Goblin", 100, 15, 10);
            anotherGoblin.DisplayStatus();
        }
    }
    

    이 경우, 같은 유형의 적을 생성할 때마다 모든 속성을 반복해서 지정해야 하는 비효율성이 발생한다.

     

    패턴 적용 예시 코드(2)

    프로토타입 패턴을 사용하면 이러한 문제를 해결할 수 있다.

    using System;
    
    interface IEnemyPrototype
    {
        IEnemyPrototype Clone();
    }
    
    class Enemy : IEnemyPrototype
    {
        public string Type { get; set; }
        public int Health { get; set; }
        public int Attack { get; set; }
        public int Defense { get; set; }
    
        public Enemy(string type, int health, int attack, int defense)
        {
            Type = type;
            Health = health;
            Attack = attack;
            Defense = defense;
        }
    
        public IEnemyPrototype Clone()
        {
            return this.MemberwiseClone() as Enemy;
        }
    
        public void DisplayStatus()
        {
            Console.WriteLine($"{Type} - Stats:");
            Console.WriteLine($"Health: {Health}, Attack: {Attack}, Defense: {Defense}");
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Enemy originalGoblin = new Enemy("Goblin", 100, 15, 10);
            originalGoblin.DisplayStatus();
    
            // 프로토타입을 사용하여 복사본 생성
            Enemy clonedGoblin = originalGoblin.Clone() as Enemy;
            clonedGoblin.DisplayStatus();
        }
    }
    

     

    프로토타입 패턴을 적용함으로써, 한 번 초기화된 적의 객체를 복제하여 새로운 객체를 생성할 수 있다. 이 방식은 특히 초기화 비용이 크거나, 객체의 생성 과정이 복잡할 때 유용하다. 게임에서 같은 유형의 적을 여러 번 생성해야 하는 경우, 이 패턴은 코드의 중복을 줄이고 성능을 개선하는 데 도움을 준다.