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 객체를 리턴해준다. - 위의 코드는
Profiler
를Factory
를 적용하여,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 변수만 추가해주면 동일하게 사용할 수 있다.