Prototype Pattern

유비쿼터스 언어 : Prototype (이하 프로토타입)

프로토타입이란? 주로 실제 제품을 만들기에 앞서 대략적인 샘플 정도의 의미로 사용되는 단어. 시제품. 초기모델.
출처 : 위키백과

프로토타입 패턴

GOF가 정의한 생성패턴(인스턴스를 만드는 절차를 추상화한 패턴)
프로토타입 패턴을 통하여 유연성을 확보할 수 있다.
객체의 생성에 대한 비용을 줄일 수 있다.
객체의 원형인 프로토타입을 이용하여 새로운 객체를 만들어내는 프로그래밍.

프로토타입 패턴의 클래스 다이어그램

Prototype : 인스턴스를 복사하여 새로운 인스턴스를 만들기 위한 메소드를 결정한다.
ConcretePrototype : 인스턴스를 복사하여 새로운 인스턴스를 만드는 메소드를 실제로 구현한다.
Client : 인스턴스 복사 메소드를 사용하여 새로운 인스턴스를 생성한다.

예제

그림그리기

ShapeType.ts

export enum ShapeType { CIRCLE, RECTANGLE, TRIANGLE, }
JavaScript
복사
미리 Shape타입의 종류를 열거합니다.

Shape.ts

import { ShapeType } from './ShapeType'; interface Cloneable { clone : () => any; } class Shape implements Cloneable { protected type: ShapeType; draw() {} clone() { console.log(this); return Object.create(this); } } export default Shape;
JavaScript
복사
자바에서 clone이 여기서는 create입니다.

Circle.ts, Triangle.ts, Rectangle.ts

Circle 만 예제로 하였음.
import Shape from './Shape'; import { ShapeType } from './ShapeType'; class Circle extends Shape { constructor() { super(); this.type = ShapeType.CIRCLE; } draw(): string { console.log('CIRCLE 입니다.'); return '🔴'; } } export default Circle;
JavaScript
복사

ShapeStore.ts

import Circle from './Circle'; import Rectangle from './Rectangle'; import Triangle from './Triangle'; import { ShapeType } from './ShapeType'; class ShapeStore { static shapeMap = new Map<ShapeType, any>(); registerShape() { const rectangle = new Rectangle(); const circle = new Circle(); const triangle = new Triangle(); ShapeStore.shapeMap.set(ShapeType.CIRCLE, circle); ShapeStore.shapeMap.set(ShapeType.RECTANGLE, rectangle); ShapeStore.shapeMap.set(ShapeType.TRIANGLE, triangle); } getShape(type: ShapeType) { return ShapeStore.shapeMap.get(type).clone(); } } export default ShapeStore;
JavaScript
복사

index.html

<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script defer type="application/javascript" src="index.js"></script> <title>그려보아요</title> </head> <body> <button id="circle"> 동그라미 그리기 🔴 </button> <button id="triangle"> 삼각형 그리기 🔺 </button> <button id="rectangle"> 네모 그리기 🟥 </button> <button id="all"> 전부 그리기 </button> <hr> <div> <span>도화지 ⬇ </span> <div id="drawing_paper"/> </div> </body> </html>
JavaScript
복사

index.ts (Main)

import ShapeStore from './ts/ShapeStore'; import { ShapeType } from './ts/ShapeType'; const $circle = <HTMLInputElement>document.querySelector('#circle'); const $triangle = <HTMLInputElement>document.querySelector('#triangle'); const $rectangle = <HTMLInputElement>document.querySelector('#rectangle'); const $all = <HTMLInputElement>document.querySelector('#all'); const $drawingPaper = <HTMLInputElement>document.querySelector('#drawing_paper'); const manager = new ShapeStore(); manager.registerShape(); $circle.onclick = () => { const cir = manager.getShape(ShapeType.CIRCLE); $drawingPaper.innerHTML = cir.draw(); }; $rectangle.onclick = () => { const rec = manager.getShape(ShapeType.RECTANGLE); $drawingPaper.innerHTML = rec.draw(); }; $triangle.onclick = () => { const tri = manager.getShape(ShapeType.TRIANGLE); $drawingPaper.innerHTML = tri.draw(); }; $all.onclick = () => { const manager = new ShapeStore(); manager.registerShape(); const cir = manager.getShape(ShapeType.CIRCLE); const rec = manager.getShape(ShapeType.RECTANGLE); const tri = manager.getShape(ShapeType.TRIANGLE); const all = `${cir.draw()} ${rec.draw()} ${tri.draw()}`; $drawingPaper.innerHTML = all; };
JavaScript
복사
→ 단점 : 얕은 복사를 진행할때는 쉽게 사용할 수 있으나, 깊은 복사를 통하여 객체를 복사해야할 경우 순환참조에 대한 생각을 해야만 합니다.

Reference