본문 바로가기
Personal-Study/Design Patterns

[TS Design Patterns] 생성 패턴 - 프로토타입

by Aaron-Kim 2023. 10. 21.

Prototype (Clone)

- 코드를 클래스에 의존시키지 않고, 기존 객체들을 복사할 수 있도록 하는 생성 패턴

- 객체를 외부에서부터 복사하는 것은 항상 가능하지 않음 (private 필드 존재 가능)

- 객체를 복제하려면 해당 객체의 클래스를 알아야 하므로 의존적임

- 프로토타입 패턴은 실제로 복제되는 객체들에 복제 프로세스를 위임함

- 프로토타입이란 복제를 지원하는 객체임

- 미리 만들어진 프로토타입은 서브 클래스의 대안이 될 수 있음

- 코드를 기하학적 객체들의 클래스들에 결합하지 않고도 해당 객체들의 정확한 복사본 생성 가능

 

- 동일 타입의 여러 객체들이 프로퍼티를 공유함

- JS 객체의 기본 속성이고 Prototype 체인 활용 가능

- 생성자의 prototype 프로퍼티 혹은
  생성된 인스턴스의 __proto__ 프로퍼티 또는 Object.getPrototypeOf (표준)를 통해 Prototype 객체 확인 가능

- 객체들이 같은 프로퍼티를 가져야 하는 경우 유용하게 쓰일 수 있음

- Prototype 객체 자체도 proto 속성을 가질 수 있음

- 현재 객체에 없는 프로퍼티에 접근하려고 할 때, JS는 같은 이름의 프로퍼티를 찾을 때까지

   재귀적으로 객체의 proto를 따라 거슬러 올라감

- Object.create()는 Prototype으로 쓰일 객체를 인자로 받아 새로운 객체를 만들어 냄,

   단순히 객체가 다른 객체로부터 프로퍼티를 상속받을 수 있게 해줌

- 메서드 중복을 줄일 수 있고 이는 메모리 절약으로 이어짐

 

- 예시

/**
 * The example class that has cloning ability. We'll see how the values of field
 * with different types will be cloned.
 */
class Prototype {
  public primitive: any;
  // @ts-ignore
  public component: object;
  // @ts-ignore
  public circularReference: ComponentWithBackReference;

  public clone(): this {
    const clone = Object.create(this);

    clone.component = Object.create(this.component);

    // Cloning an object that has a nested object with backreference
    // requires special treatment. After the cloning is completed, the
    // nested object should point to the cloned object, instead of the
    // original object. Spread operator can be handy for this case.
    clone.circularReference = {
      ...this.circularReference,
      prototype: { ...this },
    };

    return clone;
  }
}

class ComponentWithBackReference {
  public prototype;

  constructor(prototype: Prototype) {
    this.prototype = prototype;
  }
}

/**
 * The client code.
 */
function clientCode() {
  const p1 = new Prototype();
  p1.primitive = 245;
  p1.component = new Date();
  p1.circularReference = new ComponentWithBackReference(p1);

  const p2 = p1.clone();
  if (p1.primitive === p2.primitive) {
    console.log(
      'Primitive field values have been carried over to a clone. Yay!'
    );
  } else {
    console.log('Primitive field values have not been copied. Booo!');
  }

  if (p1.component === p2.component) {
    console.log('Simple component has not been cloned. Booo!');
  } else {
    console.log('Simple component has been cloned. Yay!');
  }

  if (p1.circularReference === p2.circularReference) {
    console.log('Component with back reference has not been cloned. Booo!');
  } else {
    console.log('Component with back reference has been cloned. Yay!');
  }

  if (p1.circularReference.prototype === p2.circularReference.prototype) {
    console.log(
      'Component with back reference is linked to original object. Booo!'
    );
  } else {
    console.log('Component with back reference is linked to the clone. Yay!');
  }
}

clientCode();

 

// UI Component Design Patterns - Prototype

class Dog {
  name;

  constructor(name: string) {
    this.name = name;
  }

  bark() {
    return `Woof!`;
  }
}

const dog1 = new Dog('Daisy');
const dog2 = new Dog('Max');
const dog3 = new Dog('Spot');

// @ts-ignore
Dog.prototype.play = () => console.log('Playing now!');

// @ts-ignore
dog1.play();

 

- 활용


[아티클]

[TS 사용 예시]

[UI Component] Design Patterns - Prototype

반응형

댓글