CreationalPattern_03.Factory Method

Oct 8th 2020 by jyoon

def

Factory pattern은 사용자가(클라이언트) 원하는대로 새로운 객체를 생성한다.
객체를 생성하는 방법은 new 연산자로 생성자 함수를 호출하는 것이다.
그러나 인스턴스화 할 여러 후보 객체 중 하나를 알지 못하거나 알지 못하는 상황이 있다.
팩토리 메서드를 사용하면 사용자가 인스턴스화 할 유형에 대한 제어를 유지 하면서 객체 생성을 위임 할 수 있다.

[#POINT2]Factory Method의 핵심 목표는 확장성 이다.
Factory Method는 서로 다르지만 동시에 많은 특성(예: 메서드, 속성)을 공통으로 갖는 객체 컬렉션을 관리, 유지 관리 되는 조작하는 응용 프로그램에서 자주 사용된다.
예로 Xml, Pdf문서 및 Rtf문서가 혼합 된 문서 모음이 있다.

Participants

  • Creator

    • [#POINT1]: factory 객체는 새로운 인스턴스를 생성한다.
    • [#POINT2]: 새로운 인스턴스를 반환하는 factoryMethod(createEmployee 함수)를 구현한다.
    • code: Factory 생성자 함수
  • AbstractProduct -- not used in JavaScript

    • 인스턴스를 생성할 인터페이스를 선언한다.
    • code: 사용되지 않음
  • ConcreteProduct

    • 인스턴스가 생성되는 대상이다.
    • [#POINT2]: 모든 생성된 인스턴스가 같은 인터페이스를 지원한다(property와 함수들)
    • code: Employees 배열 객체

샘플 코드 설명

JavaScript 예제에서 Factory 객체는 네 가지 유형의 직원을 만든다.
직원 유형마다 시간당 요금이 다르다.
createEmployee 메서드는 실제 팩토리 메서드이다.
클라이언트는 유형 인수를 Factory 메서드에 전달하여 생성 할 직원 유형을 공장에 지시한다.

Javascript가 추상 클래스 또는 인터페이스를 지원하지 않기 때문에 다이어그램의 AbstractProduct는 구현되지 않는다.
그러나 모든 직원 유형이 동일한 인터페이스 (속성 및 메서드)를 갖도록해야한다.

네 가지 유형의 직원이 생성된다.
모두 동일한 배열에 저장된다.
각 직원은 자신이 무엇인지와 시간당 요금을 say한다.

나의 분석

  • Creator 역할을 하는 Factory 생성자 함수의 createEmployee함수를 통해서 다른 종류의 인스턴스를 return 한다.

    • 생성될 인스턴스 대상 생성자 함수: FullTime, PartTime, Temporary, Contractor
  • Factory 생성자함수: 팩토리 패턴 함수

    • [#POINT2]this.createEmployee: factory method(인스턴스를 생성)
    • employee.type, employee.say: factory method에 의해서 생성된 인스턴스는 같은 인터페이스를 지원 한다.
  • type, say를 여러번 생성자 함수 FullTime, PartTime, temporary, contractor마다 선언하지 않아도 된다.

CODE

var log = (function () {
  var log = '';

  return {
    add: function (msg) {
      log += msg + "\n";
    },
    show: function () {
      console.log(log);
      log = '';
    }
  }
})();

// Creator 역할
function Factory() {
  // [#POINT2]: factory method이다.
  this.createEmployee = function (type) {
    var employee;

    if (type === 'fulltime') {
      // [#POINT1]
      employee = new FullTime();
    } else if (type === 'parttime') {
      // [#POINT1]
      employee = new PartTime();
    } else if (type === 'temporary') {
      // [#POINT1]
      employee = new Temporary();
    } else if (type === 'contractor') {
      // [#POINT1]
      employee = new Contractor();
    }
    employee.type = type;

    employee.say = function () {
      log.add(`${this.type}: rate ${this.hourly} /hour`);
    }

    return employee;
  }
}

// ConcreteProduct로 만들어질 대상
var FullTime = function () {
  this.hourly = "$12";
}
// ConcreteProduct로 만들어질 대상
var PartTime = function () {
  this.hourly = "$11"
}
// ConcreteProduct로 만들어질 대상
var Temporary = function () {
  this.hourly = "$10"
}
// ConcreteProduct로 만들어질 대상
var Contractor = function () {
  this.hourly = "$15"
}

function run() {
  // ConcreteProduct 역할 배열 객체
  var employees = [];
  var factory = new Factory();

  employees.push(factory.createEmployee("fulltime"));
  employees.push(factory.createEmployee("parttime"));
  employees.push(factory.createEmployee("temporary"));
  employees.push(factory.createEmployee("contractor"));

  for (var i = 0, len = employees.length; i < len; i++) {
    employees[i].say();
  }

  log.show();
}

run();