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();
- 활용
반응형
'Personal-Study > Design Patterns' 카테고리의 다른 글
[TS Design Patterns] 구조 패턴 - 어댑터 (2) | 2023.10.23 |
---|---|
[TS Design Patterns] 생성 패턴 - 싱글톤 (0) | 2023.10.21 |
[TS Design Patterns] 생성 패턴 - 빌더 (0) | 2023.10.21 |
[TS Design Patterns] 생성 패턴 - 팩토리 메서드 (0) | 2023.10.21 |
[TS Design Patterns] 생성 패턴 - 추상 팩토리 (0) | 2023.10.19 |
댓글