프로토타입 패턴

정선호·2023년 5월 11일
0

Design Patterns

목록 보기
11/24

관련 영상

프로토타입 패턴

위키피디아
설명 및 스도코드

  • 코드를 그들의 클래스들에 의존시키지 않고 기존 객체들을 복사할 수 있도록 하는 생성 디자인 패턴
  • 생성할 객체들의 타입이 프로토타입인 인스턴스로부터 결정되도록 하며, 인스턴스는 새 객체를 만들기 위해 자신을 복제(clone)하게 된다

프로토타입 패턴의 구조

  • 프로토타입 인터페이스(Prototype Interface)
    • 복제 메서드들을 선언하며 이 메서드들의 대부분은 단일 clone()메서드이다
  • 구상 프로토타입(Concrete Prototype)
    • 복제 메서드를 구현한다.
    • 원본 객체의 데이터를 복제본에 복사하는 것 외에도 이 메서드는 복제 프로세스와 관련된 일부 예외적인 경우들도 처리할 수 있다.
  • 클라이언트
    • 프로토타입 인터페이스를 따르는 모든 객체의 복사본 생성 가능
  • 프로토타입 레지스트리(Prototype Registrt)
    • 자주 사용하는 프로토타입들에 쉽게 접근하는 방법 제공
    • 복사될 준비가 된 미리 만들어진 객체들의 집합을 저장함
    • 가장 간단한 프로토타입 레지스트리는 name->prototype 해시맵

프로토타입의 적용

  • 복사하는 객체들의 구상 클래스들에 코드가 의존하면 안될 때
    • 이와 같은 경우는 코드가 어떤 인터페이스를 통해 타사 코드에서 전달된 객체들과 함께 작동할 때 많이 발생함
    • 프로토타입 패턴은 클라이언트 코드에 복제를 지원하는 모든 객체와 작업할 수 있도록 일반 인터페이스를 제공. 이 인터페이스는 클라이언트 코드가 복제하는 객체들의 구상 클래스들에서 클라이언트 코드를 독립시킨다.
  • 각자의 객체를 초기화하는 방식만 다른 자식 클래스들의 수를 줄이고 싶을 때 사용
    • 프로토타입 패턴은 다양한 방식으로 설정된 미리 만들어진 객체들의 집합을 프로토타입들로 사용할 수 있도록 한다. 일부 설정과 일치하는 자식 클래스를 인스턴스화하는 대신 클라이언트는 간단하게 적절한 프로토타입을 찾아 복제할 수 있다.

다른 패턴과의 관계

  • 많은 디자인은 복잡성이 낮고 자식 클래스들을 통해 더 많은 커스터마이징이 가능한 팩토리 메서드로 시작해 더 유연하면서도 더 복잡한 추상 팩토리, 프로토타입 또는 빌더 패턴으로 발전해 나간다.
  • 추상 팩토리 클래스들은 팩토리 메서드들의 집합을 기반으로 하는 경우가 많다. 그러나 프로토타입을 사용하여 추상 팩토리의 구상 클래스들의 생성 메서드들을 구현할 수도 있다.
  • 프로토타입은 커맨드 패턴의 복사본들을 기록에 저장해야 할 때 도움이 될 수 있다.
  • 데코레이터 및 복합체 패턴을 많이 사용하는 디자인들은 프로토타입을 사용하면 종종 이득을 볼 수 있다. 프로토타입 패턴을 적용하면 복잡한 구조들을 처음부터 다시 건축하는 대신 복제할 수 있기 때문
  • 프로토타입은 상속을 기반으로 하지 않으므로 상속과 관련된 단점들이 없다. 반면에 프로토타입은 복제된 객체의 복잡한 초기화가 필요하다. 팩토리 메서드는 상속을 기반으로 하지만 초기화 단계가 필요하지 않다.
  • 때로는 프로토타입이 메멘토 패턴의 더 간단한 대안이 될 수 있으며, 이 패턴은 상태를 기록에 저장하려는 객체가 간단하고 외부 리소스에 대한 링크가 없거나 링크들이 있어도 이들을 재설정하기 쉬운 경우에 작동한다.
  • 추상 팩토리들, 빌더들 및 프로토타입들은 모두 싱글턴으로 구현할 수 있다.

유니티로 구현한 유닛 클론 소환

  • 프로토타입 인터페이스
public interface IUnit
{
    // Method for cloning
    IUnit Clone();
}
  • 콘크리트 프로토타입
    • MemberwiseClone() 함수는 얕은 복사로 단순 복사본 객체를 생성해 리턴하는 함수
// 'ConcretePrototype1' class implements IPrototype interface
public class Marine : IUnit
{
    public int Hp { get; set; }
    public int AttackPower { get; set; }

    // Implement shallow cloning method
    public IUnit Clone()
    {
        // Shallow Copy
        return this.MemberwiseClone() as IUnit;

        // Deep Copy
        // Implement Memberwise clone method for every reference type object 
        // return ..
    }
}

public class Firebat : IUnit
{
    public int Age { get; set; }
    public int AttackPower { get; set; }

    // Implement shallow cloning method
    public IUnit Clone()
    {
        // Shallow Copy 
        return this.MemberwiseClone() as IUnit;
    }
}
  • 클라이언트
public class UnitManager : MonoBehaviour {

	void Start () {
        Marine marine = new Marine();
        marine.Hp = 25;
        marine.AttackPower = 5;

        // clone Marine object with Clone method
        // If you will not set the new value for any field the it will take the default value
        // from original object
        Marine marineClone = (Marine)marine.Clone();
        marineClone.Hp = 30;  // 값만 수정해준다.
        marineClone.AttackPower = 6;  // 값만 수정해준다.

        Debug.Log("Marine Details");
        Debug.LogFormat("Age: {0} / AttackPower: {1}",marine.Hp, marine.AttackPower);

        Debug.Log("Cloned Marine Details");
        Debug.LogFormat("Age: {0} / AttackPower: {1}", marineClone.Hp, marineClone.AttackPower);

        // you can perform the same operation for Firebat
    }
}
profile
학습한 내용을 빠르게 다시 찾기 위한 저장소

0개의 댓글