유비쿼터스 언어 : 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
복사
→ 단점 : 얕은 복사를 진행할때는 쉽게 사용할 수 있으나, 깊은 복사를 통하여 객체를 복사해야할 경우 순환참조에 대한 생각을 해야만 합니다.