Instantiation Patterns

자료구조 Stack, Queue 으로 구현

Class 선언이 나오기 전 사용되었던 4가지 방법

Pseudoclassical (prototype 선언 방식은 현재도 많이 쓰임)

1. Functional

2. Functional-shared

3. Prototypal

4. Pseudoclassical

1. Functional

  • 함수를 이용하여 찍어내는 방식

    • Functional - Stack

const Stack = function() {
  let stackInstance = {};
  let storage = {}; // stack의 데이터를 담을 공간을 생성
  let count = 0; // storage의 key가 될것이며, size 확인시 사용됨

  stackInstance.push = function(value) {
    storage[count] = value; // storage의 key - count , value - value 삽입
    count++;
  };

  stackInstance.pop = function() {
    if (count === 0) return; // 스택에 담긴 아이템이 없는 경우 undefined를 반환
    let deletedItem = storage[count - 1];
    delete storage[count - 1];
    count--;
    return deletedItem;
  };

  stackInstance.size = function() {
    return count;
  };

  return stackInstance; // 인스턴스의 객체를 반환할 수 있게 리턴이 반드시 필요
};
let myStack = Stack();
myStack.push('a');
myStack.push('b');
myStack.pop(); // b
myStack.pop(); // a
myStack.pop(); // undefined
myStack.size(); // 0
  • Stack 이라는 Constructor 함수 생성
  • 함수안에 stackInstance라는 객체를 생성하고 그 안에 메소드를 넣는다.
  • return stackInstance를 통해 생성된 객체를 반환한다.

2. Functional-shared

  • 인스턴스가 사용할 메소드를 따로 만들어서 주소값을 참조하는 형식

  • 각각의 인스턴스가 같은 메소드를 참조하기 때문에 메모리 효율이 좋아짐

    • (불필요한 메모리 사용 방지)
    • Functional-shared - Queue

// 메소드를 참조하는 함수를 생성
const extend = function(to, from) {
  for (let key in from) {
    to[key] = from[key];
  }
};
// queue에 사용될 method 생성
const queueMethods = {
  enqueue: function(value) {
    this.storage[this.index] = value;
    this.index++;
  },
  dequeue: function() {
    if (this.index === this.delIndex) return; // index와 삭제할index가 같으면 undefined;
    let delItem = this.storage[this.delIndex]; // 사용될데이터를 변수로 생성
    delete this.storage[this.delIndex]; // 데이터를 사용
    this.delIndex++; // 삭제할index의 값을 추가
    return delItem;
  },
  size: function() {
    return this.index - this.delIndex;
  }
};
// queue의 클래스 생성(method 제외)
const Queue = function() {
  let queueInstance = {
    storage: {},
    index: 0,
    delIndex: 0
  };
  extend(queueInstance, queueMethods); ///////////// queueInstance에 queueMethods를 참조
  return queueInstance;
};

3. Prototypal

  • Functional-shared 와 비슷하지만 method를 참조하는 방식이 다름

  • Object.create 를 통해 method를 prototype으로 하는 객체를 생성

    • Prototypal - Stack

const stackMethods = {
  push: function(value) {
    this.storage[this.count] = value;
    this.count++;
  },
  pop: function() {
    if (this.count === 0) return;
    let delItem = this.storage[this.count - 1];
    delete this.storage[this.count - 1];
    this.count--;
    return delItem;
  },
  size: function() {
    return this.count;
  }
};

const Stack = function() {
  let stackInstance = Object.create(stackMethods);
  stackInstance.storage = {};
  stackInstance.count = 0;
  return stackInstance;
};

4. Pseudoclassical

  • 클래스가 될 Queue 함수 작성

  • Queue의 prototype에 method를 추가

  • 인스턴스 생성시 new 키워드 사용

    • Pseudoclassical - Queue

const Queue = function() {
  this.storage = {};
  this.index = 0;
  this.delIndex = 0;
};

Queue.prototype.enqueue = function(value) {
  this.storage[this.index] = value;
  this.index++;
};

Queue.prototype.dequeue = function() {
  if (this.index === this.delIndex) return;
  let delItem = this.storage[this.delIndex];
  delete this.storage[this.delIndex];
  this.delIndex++;
  return delItem;
};

Queue.prototype.size = function() {
  return this.index - this.delIndex;
};
let myQueue = new Queue(); // new 를 이용하여 인스턴스 생성
myQueue.enqueue('a'); // a;
myQueue.dequeue(); // a;
myQueue.size(); // 0;