ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 프로토타입 패턴(Prototype Pattern)이란?
    Design Pattern/생성 디자인 패턴 2024. 4. 2. 22:35
    반응형

    1. 프로토타입 패턴이란?

     프로토타입 패턴은 생성 디자인 패턴의 한 종류로, 기존 객체를 복제하여 새 객체를 생성하는 방식입니다. 이 패턴은 특히 객체 생성 비용이 크거나 복잡한 경우, 또는 클라이언트가 객체의 타입을 미리 알 수 없는 경우에 유용합니다. 프로토타입 패턴은 원본 객체의 정확한 복사본을 제공함으로써, 새 객체의 생성과 초기화 과정을 단순화합니다.

    2. 프로토타입 패턴은 주로 어디에 쓰이나?

    프로토타입 패턴은 다음과 같은 상황에서 주로 사용됩니다:

    • 객체 생성 비용이 높고, 비슷한 객체가 여러 개 필요한 경우
    • 객체의 타입이 런타임에 결정되는 경우
    • 클론을 지원하여 객체의 상태를 쉽게 복제할 수 있는 경우

     이 패턴은 게임 개발에서 캐릭터, 아이템 등의 인스턴스를 만들 때나, 소프트웨어 개발에서 설정 정보의 복제본을 생성할 때 유용하게 쓰일 수 있습니다.

    3. Java와 Go로 프로토타입 패턴을 구현할 때의 차이점

    Java와 Go 둘 다 프로토타입 패턴을 지원하지만, 구현 메커니즘에서 차이가 있습니다:

    • Java: Java에서는 Cloneable 인터페이스를 구현하고 clone() 메소드를 오버라이드하여 객체를 복제합니다. clone() 메소드는 CloneNotSupportedException을 던질 수 있으므로, 이를 적절히 처리해야 합니다.
    • Go: Go에서는 복제할 객체의 인터페이스에 Clone() 메소드를 정의하고, 해당 메소드 내에서 새 객체를 생성하여 복제합니다. Go의 내장 기능을 사용하여 구조체 필드를 깊은 복사하는 방법도 있습니다.

    4. 프로토타입 패턴 예시 (Java, Golang)

    Java 예시

    public interface Prototype {
        Prototype clone();
    }
    
    public class ConcretePrototype implements Prototype {
        private String field;
    
        public ConcretePrototype(String field) {
            this.field = field;
        }
    
        @Override
        public Prototype clone() {
            return new ConcretePrototype(this.field);
        }
    }

     

    Java 예시: 상속과 인터페이스를 활용한 복잡한 객체 복제

    Java에서는 Cloneable 인터페이스와 clone() 메서드를 활용하여 객체를 복제합니다. 여기서는 상속과 컴포지션을 통해 보다 복잡한 구조의 객체 복제를 입니다.

    public interface PrototypeCapable extends Cloneable {
        PrototypeCapable clone() throws CloneNotSupportedException;
    }
    
    class ConcreteComponent implements PrototypeCapable {
        private String name;
    
        // Constructors, getters and setters
    
        @Override
        public ConcreteComponent clone() throws CloneNotSupportedException {
            return (ConcreteComponent) super.clone();
        }
    }
    
    class CompositeObject implements PrototypeCapable {
        private String id;
        private List<PrototypeCapable> components = new ArrayList<>();
    
        // Constructors, getters and setters
    
        public void addComponent(PrototypeCapable component) {
            components.add(component);
        }
    
        @Override
        public CompositeObject clone() throws CloneNotSupportedException {
            CompositeObject clone = (CompositeObject) super.clone();
            clone.components = new ArrayList<>(this.components.size());
            for (PrototypeCapable component : this.components) {
                clone.addComponent(component.clone());
            }
            return clone;
        }
    }

     이 예시에서 ConcreteComponent 클래스는 간단한 구성 요소를 나타내고, CompositeObject 클래스는 여러 PrototypeCapable 객체를 포함할 수 있는 복합 객체를 나타냅니다. CompositeObjectclone 메서드는 깊은 복사를 수행하여 모든 구성 요소도 복제합니다.

     

    Golang 예시

    package main
    
    import "fmt"
    
    type Prototype interface {
        Clone() Prototype
    }
    
    type ConcretePrototype struct {
        field string
    }
    
    func (p *ConcretePrototype) Clone() Prototype {
        return &ConcretePrototype{field: p.field}
    }
    
    func main() {
        original := &ConcretePrototype{field: "value"}
        cloned := original.Clone()
        fmt.Println(original, cloned)
    }

     

    Go 예시: 인터페이스와 구조체 포인터를 이용한 복잡한 객체 복제

     Go에서는 인터페이스를 통해 복제 가능한 객체를 정의할 수 있습니다. 여기서는 구조체와 포인터를 이용하여 복잡한 객체의 복제를 구현해보겠습니다.

    package main
    
    import "fmt"
    
    type Prototype interface {
        Clone() Prototype
    }
    
    type ConcreteComponent struct {
        name string
    }
    
    func (c *ConcreteComponent) Clone() Prototype {
        return &ConcreteComponent{name: c.name}
    }
    
    type CompositeObject struct {
        id        string
        components []Prototype
    }
    
    func (co *CompositeObject) AddComponent(component Prototype) {
        co.components = append(co.components, component)
    }
    
    func (co *CompositeObject) Clone() Prototype {
        clone := &CompositeObject{id: co.id}
        for _, component := range co.components {
            clone.AddComponent(component.Clone())
        }
        return clone
    }
    
    func main() {
        // Example usage
    }

    이 예시에서는 ConcreteComponent 구조체가 단일 구성 요소를, CompositeObject 구조체가 여러 구성 요소를 포함하는 복합 객체를 나타냅니다. CompositeObjectClone 메서드는 내부 구성 요소까지 깊은 복사를 수행하여 복제합니다.

    5. 프로토타입 패턴의 장단점

    장점:

    • 복잡한 객체의 생성과 초기화 과정을 단순화
    • 객체의 생성 비용이 높은 경우 성능 향상
    • 클라이언트가 특정 객체 타입을 몰라도 객체를 복제할 수 있음

    단점:

    • 깊은 복사와 얕은 복사 사이에서 선택해야 할 때 발생하는 복잡성
    • 복제 과정에서 순환 참조가 있을 경우 문제 발생 가능성

     프로토타입 패턴은 객체의 생성과 초기화 과정을 간소화하고, 동적으로 객체의 타입을 다룰 수 있게 하는 강력한 도구입니다. Java와 Go에서의 구현 예를 통해, 언어별 차이점을 이해하고 적절히 활용할 수 있습니다.

    반응형
Designed by Tistory.