본문 바로가기
Design Pattern/Creational Design

[Design Pattern] (Creational) 프로토타입 패턴(Prototype Pattern)

by song.ift 2023. 3. 26.

디자인 패턴 유형

  • Creation Design Pattern
    • 객체의 생성에 관련된 패턴
    • 객체의 생성 로직을 숨김으로써 유연성을 향상시킨다.
  • Strutural Design Pattern
    • 클래스와 객체의 구성에 관련된 패턴
  • Behavioral Design Pattern
    • 객체와 객체 간의 통신에 관련된 패턴

 

[Creational Design Pattern] 프로토타입 패턴(Prototype Pattern)

prototype 디자인 패턴은 다른 객체의 프로토 타입 역할을하는 객체를 만드는 프로토 타입 상속을 기반으로한다고 생각할 수 있다.프로토타입 패턴은 객체를 효율적으로 생성하는 방식으로  객체의 템플릿을 기반으로 새로운 객체를 만들 수 있다.

프로토타입 개체 자체는 생성자가 만드는 각 개체의 청사진으로 효과적으로 사용되며, 전달된 원본 객체의 복제본(얕은 복제본)이다. 사용된 생성자 함수의 프로토 타입에 name과 같은 속성이 들어 있으면 (코드 샘플의 아래쪽에서와 같이) 동일한 생성자가 만든 각 객체에도 동일한 속성이 있다.

 

장점

  • 생성된 원본 객체를 복사해서 사용하기 때문에, 객체를 생성하는 비용이 클 때 그리고 성능이 중요한 상황에서 사용할 수 있다.
    • 광범위한 데이터베이스 작업을 수행하여 애플리케이션의 다른 부분에 사용되는 객체를 만드는 것이다. 다른 프로세스가 이 객체를 사용해야 할 경우, 데이터베이스 작업을 수행하는 대신 이전에 만든 객체를 복제하는 것이 좋다.
  • 프로토타입 패턴은 다른 언어의 기능을 모방하지 않고, JavaScript가 제공해야하는 프로토타입의 강점과 함께 작업한다는 것이다. 다른 디자인 패턴의 경우 항상 그렇지는 않습니다.
    • 프로토타입 패턴은 상속을 기반으로 하지만, JavaScript는 Object의 create() 메소드를 활용하여 손쉽게 구현이 가능하다

즉 프로토타입 패턴은 상속을 구현하는 쉬운 방법 일뿐만 아니라 성능을 향상시킬수도 있으며, 객체에서 함수를 정의 할 때 참조로 작성된다. (모든 하위 객체는 동일한 함수를 가리킨다) 

 

 

ex)

Object.create는 지정된 프로토 타입을 가지며 선택적으로 지정된 속성 (예 : Object.create (prototype, optionalDescriptorObjects))을 포함하는 객체를 만든다.

 
javascript
닫기
var myCar = { ​​name: "Ford Escort", ​​drive: function () { ​​​​console.log( "Weeee. I'm driving!" ); ​​}, ​​panic: function () { ​​​​console.log( "Wait. How do you stop this thing?" ); ​​} }; var yourCar = Object.create( myCar ); console.log( yourCar.name );

 

또한 Object.create를 사용하면 객체가 다른 객체에서 직접 상속받을 수있는 차등 상속과 같은 고급 개념을 쉽게 구현할 수 있다. Object.create를 사용하면 두 번째 제공된 인수를 사용하여 객체 속성을 초기화 할 수 있다.

javascript
닫기
var vehicle = { ​​getModel: function () { ​​​​console.log( "The model of this vehicle is.." + this.model ); ​​} }; var car = Object.create(vehicle, { ​​"id": { ​​​​value: MY_GLOBAL.nextId(), ​​​​enumerable: true ​​}, ​​"model": { ​​​​value: "Ford", ​​​​enumerable: true ​​} });
javascript
닫기
class Car { ​​constructor (_wheels) { ​​​​this.noOfWheels = _wheels; ​​} ​​ ​​start() { ​​​​return `start ${this.noOfWheels}`; ​​} ​​ ​​stop() { ​​​​return `stop ${this.noOfWheels}`; ​​} } const car = new Car(4); const cloneCar1 = Object.create(car, { owner: { value: 'Mung1' } }); const cloneCar2 = Object.create(car, { owner: { value: 'Mung2' } }); console.log(cloneCar1.__proto__ === car); // true console.log(cloneCar2.__proto__ === car); // true cloneCar2.noOfWheels += 10 console.log(cloneCar1.start()) // start 4 console.log(cloneCar1.stop()) // stop 4 console.log(cloneCar1.noOfWheels) // 4 console.log(cloneCar1.owner) // Mung1 console.log(cloneCar2.noOfWheels) // 14

여기에서 앞서 살펴본 Object.defineProperties 및 Object.defineProperty 메서드에서 사용되는 것과 유사한 구문을 사용하여 개체 리터럴을 사용하여 Object.create의 두 번째 인수에서 속성을 초기화 할 수 있다.

 

Object.create를 직접 사용하지 않고 프로토 타입 패턴을 구현하려는 경우 다음과 같이 패턴을 위에서와 같이 시뮬레이트 할 수 있다.

javascript
닫기
var vehiclePrototype = { ​​init: function ( carModel ) { ​​​​this.model = carModel; ​​}, ​​ ​​getModel: function () { ​​​​console.log( "The model of this vehicle is.." + this.model); ​​} }; function vehicle( model ) { ​​function F() {}; ​​F.prototype = vehiclePrototype; ​​var f = new F(); ​​f.init( model ); ​​return f; } var car = vehicle( "Ford Escort" ); car.getModel();

이 대안에서는 사용자가 동일한 방식으로 읽기 전용 속성을 정의 할 수 없다 (주의하지 않으면 vehiclePrototype이 변경 될 수 있음).

javascript
닫기
var beget = (function () { ​​​​function F() {} ​​​​return function ( proto ) { ​​​​​​​​F.prototype = proto; ​​​​​​​​return new F(); ​​​​}; })();

댓글