Link Search Menu Expand Document

Factory Pattern

  • 비슷한 객체를 공장에서 찍어내듯이 반복적으로 생성할 수 있게 하는 패턴
  • 객체의 생성을 구현과 분리할 수 있게 해준다.
  • 새로운 인스턴스의 생성을 감싸서, 구현에 있어서 유연성과 제어력을 제공한다.
  • 팩토리를 제공해줄 경우, 팩토리 사용자는 인스턴스의 생성이 수행되는 방법에 대해서는 알필요가 없어진다.
let myImg;
if (name.match(/\.jpeg$/)) {
    myImg = new JpegImage(name);
  } else if (name.match(/\.GifImage$/)) {
    myImg = new GifImage(name);
  }

// Factory Pattern
function createImage(name) {
  if (name.match(/\.jpeg$/)) {
    return new JpegImage(name);
  } else if (name.match(/\.GifImage$/)) {
    return new GifImage(name);
  } else {
    return new Exception("Err");
  }
}
    
let myImg = createImage("profile.jpeg")

Encapsulation

  • javascript에는 접근 수준 지정자, 즉 java등에서 사용되는 private 변수를 사용할 수 없다.
  • 없었다.(있어진듯 하지만 많이 사용되지는 않는듯 하다)
  • Factory Pattern과 javascript의 scope, closure를 활용하면 private 변수와 유사한 효과를 낼 수 있다.
  function createPerson(name) {
  const privateProperties = {};

  const person = {
    setName: (name) => {
      if (!name) throw new Error("A person must have name");
      privateProperties.name = name;
    },
    getName: () => {
      return privateProperties.name;
    },
  };

  person.setName(name);
  return person;
}

const p1 = createPerson("saeeng");


console.log(p1.getName()); // saeeng
console.log(p1); //setName, getName

  • 위 코드에서 person의 name은 getName()로만 접근이 가능해진다.

DuckTyping

만약 어떤 새가 오리처럼 걷고, 헤엄치고, 꽥꽥거리는 소리를 낸다면 나는 그 새를 오리라고 부를 것이다.

  • 덕 타이핑(duck typing)은 동적 타이핑의 한 종류로, 객체의 변수 및 메소드의 집합이 객체의 타입을 결정하는 것을 말한다.
class Profiler {
  constructor(label) {
    this.label = label;
    this.lastTime = null;
  }
  start() {
    this.lastTime = process.hrtime();
  }
  end() {
    const diff = process.hrtime(this.lastTime);
    console.log(
      `Timer ${this.label} took ${diff[0]} seconds and ${diff[1]} nanoseconds`
    );
  }
}

module.exports = function (label) {
  if (process.env.NODE_ENV === "development") {
    return new Profiler(label);
  } else if (process.env.NODE_ENV === "production") {
    return {
      start: () => {},
      end: () => {},
    };
  } else {
    throw new Error("Must set NODE_ENV");
  }
};


const profiler = require("./profiler");

function getRandomArray(len) {
  const p = profiler(`Generating a ${len} items long array`);
  p.start();
  const arr = [];
  for (let i = 0; i < len; i++) {
    arr.push(Math.random());
  }
  p.end();
}

getRandomArray(1e7);
console.log("Done");
$ export NODE_ENV=production; node profilerTest
Done

$ export NODE_ENV=development; node profilerTest
Timer Generating a 10000000 items long array took 0 seconds and 305974800 nanoseconds
Done

  • profiler class는 함수의 동작 시간을 로그하는 간단한 class이다.
  • node 환경에서 위의 Profiler와 같은 logger 함수들은 process.NODE_ENV 를 통하여 동작을 제어하며 사용하게 된다.
  • development 환경에서 정상적으로 작동하는 Profiler와 production 환경에서 자리를 채워줄 mock 객체를 리턴해준다.
  • 위의 코드는 ProfilerFactory를 적용하여, Profiler 사용자가 노드 환경에 대한 별도의 처리없이 사용할 수 있게 해준다. => 앞서 말한 객체의 생성과 구현을 분리할 수 있게 되었다.
  • 추가로, Typescript에서도

    One of TypeScript’s core principles is that type checking focuses on the shape that values have. This is sometimes called “duck typing” or “structural subtyping”.

  • 즉, 타입 검사를 shape 측면에서 지원하기 때문에, 위의 코드에서 Profiler interface를 작성한 후, mock 객체에 label 과 lastTime 변수만 추가해주면 동일하게 사용할 수 있다.