(JS) Factory Method Pattern

호두파파·2021년 3월 22일
0

호두파파 JS 스터디

목록 보기
24/27

Factory

팩토리 메서드 패턴에 팩토리(Factory)라는 이름이 붙은 이유는 공장에서 상품을 생산하듯이, 팩토리 메서드로 비슷한 객체를 찍어내는 동작을 하기 때문이다.

상위 클래스에서 로직을 공통화할 수 있는 장점이 있는 템플릿 메서드 패턴을 인스턴스 생성에 응용한 것이 팩토리 메서드 패턴이다.

하지만 JavaScript는 프로타입 기반 언어로, 원래는 Java 등지에서 사용하는 클래스라는 개념이 없다. 대신 프로토타입을 이용해 상속을 구현하거나, 혹은 new키워드와 함수를 이용해 클래서츠럼 동작하도록 흉내낼 수 있다.
(ES6에서 추가된 class는 문법적인 설탕일 뿐 내부적으로는 prototype을 이용해 구현한 것과 같다)

function Person(name) {
  this.name = name;
  this.introduce = function() {
    return 'my name is' + this.name
  }
}
// name 프로퍼티와 introduce 메소드를 미리 초기화한 객체를 리턴합니다. 
var user1 = new Person('hodoo');
var user2 = new Person('wero');

user1.introduce() // My name is hodoo
user2.introduce() // My name is wero

JavaScrpt Factory Function

new 키워드로 객체를 생성하지 않고 ES6의 Object.assign()을 사용해서 팩토리 함수를 구현할 수 있다. 이 함수는 여러 객체의 속성을 복사해서 하나로 합칠 수 있다.

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target);		 // { a: 1, b: 4, c: 5 }
console.log(returnedTarget); // { a: 1, b: 4, c: 5 }

이를 활용해 target 대신 빈 객체 {}를 넣고 여러 개의 source 객체를 인자로 넣으면, 빈 객체에 다른 객체들이 합쳐진 새로운 객체르 얻을 수 있다.

이를 연결형 상속이라고 하는데, 객체 속성을 복사함으로서 상속을 구현할 수 있다.

const jsSkill = {
  knowJS() {
    return true
  }
}

const javaSkill = {
  knowJava() {
    return true
  }
}

const isWorking = {
  isWorking() {
    return true
  }
}

const frontendEngineer = Object.assign({}, jsSkill, isWorking)
const backendEngineer = Object.assign({}, javaSkill, isWorking)
const fullStackEngineer = Object.assign({}, jsSkill, javaSkill, isWorking)

Hello, Doodle Factorry!

먼저 doodle 이라는 팩토릴 함수를 정의한다. 이 함수는 내부에서 빈 객체를 만들고 name 프로퍼티와 run 이라는 함수를 갖도록 초기화해 반환한다.

const Doodle = function(name) {
  const doodle = {};
  doodle.name = name;
  doodle.run = function() {
    console.log(this.name + ' run!');
  }
  retrun doodle;
}
const hodoo = doodle('hodoo');

이 doodle 팩토리로 만들어진 두들 친구에게 특정한 기능을 주고 싶다. canJump라는 객체를 만들고
Object.assign으로 복사를 해보자.

const canJump = {
  jump() {
    console.log('i can jump everywhere!')
  }
}
const wero = Object.assign(Doodle('wero'), canJump)

Doodle 팩토리에 만들어진 객체에게 jump()능력을 부여한 두들 wero 객체를 생성했다!

하지만 assign을 객체 생성시마다 일일이 적용해주는 것은 굉장히 불편하다. 따라서 먼저 만들었던 Doodle 팩토리에서 베이스가 되는 객체를 생성하고, Object.assign을 통해 jump능력을 가진 두들을 생산할 수 있는 JumpingDoodle이라는 팩토리 함수를 만들어보겠다.

const JumpingDoodle = function(name) {
  return Object.assign(Doodle(name), canJump)
}
const bao = JumpingDoodle('bao')

다른 예시 보기

const HumanBorn = function(obj) {
  let isWalking = false
  return Object.assign({}, obj, {
    walk() {
      isWalking = true
    },
    isWalking() {
      return isWalking
    }
  })
}

const StarkIndustry = function(obj) {
  let isFlying = false
  return Object.assign({}, obj, {
    fly() {
      isFlying = true
      return this
    },
    isFlying() {
      return isFlying
    }
  })
}

const tony = HumanBorn()
const ironman = StarkIndustry(tony)

const jarvis = StarkIndustry()
const vision = HumanBorn(jarvis)

출처

링크

profile
안녕하세요 주니어 프론트엔드 개발자 양윤성입니다.

0개의 댓글