팩토리 패턴
팩토리 패턴(Factory Pattern)은 객체 생성을 처리하는 코드와 사용자 코드를 분리하여 객체를 생성하는 패턴입니다. 팩토리 패턴을 사용하면 객체 생성을 처리하는 코드와 사용자 코드를 분리할 수 있으며, 객체를 생성하는 방식을 유연하게 변경할 수 있습니다. 객체 생성을 처리하는 코드를 단일화하여 중복 코드를 제거하고, 객체 생성에 대한 의존성을 완화할 수 있습니다.
팩토리 패턴은 크게 두 가지로 나눌 수 있습니다.
심플 팩토리 패턴
심플 팩토리 패턴(Simple Factory Pattern)은 객체 생성을 전담하는 클래스를 만들어서 객체를 생성하는 패턴입니다. 사용자는 팩토리 클래스에게 객체 생성을 요청하면 팩토리 클래스에서 객체를 생성하여 반환합니다.
심플 팩토리 패턴의 장점은 사용자 코드에서 직접 객체를 생성하지 않기 때문에 객체 생성과 사용이 분리되어 있어서 유지보수성이 좋다는 것입니다.
심플 팩토리 패턴 JavaScript 예제
JavaScript에서 심플 팩토리 패턴은 다음과 같이 구현할 수 있습니다.
Shape 클래스는 추상화된 클래스로, 실제 구현은 서브 클래스에서 처리합니다. Circle, Rectangle, Triangle 클래스는 각각 Shape 클래스를 상속하며, draw 메서드를 구현합니다. 사용자는 ShapeFactory 클래스에서 createShape 메서드를 호출하여 적절한 객체를 생성한 후, 해당 객체의 draw 메서드를 호출하여 그림을 그립니다.
// Shape 클래스 정의
class Shape {
draw() {
console.log('Drawing shape...');
}
}
// Circle 클래스 정의
class Circle extends Shape {
draw() {
console.log('Drawing a circle...');
}
}
// Rectangle 클래스 정의
class Rectangle extends Shape {
draw() {
console.log('Drawing a rectangle...');
}
}
// Triangle 클래스 정의
class Triangle extends Shape {
draw() {
console.log('Drawing a triangle...');
}
}
아래 ShapeFactory class는 심플 팩토리 패턴을 적용한 팩토리로 createShape이라는 함수를 가지고 type값에 따라 Shape을 구현하는 서로 다른 class를 반환합니다.
class ShapeFactory {
createShape(type) {
let shape;
switch (type) {
case 'circle':
shape = new Circle();
break;
case 'rectangle':
shape = new Rectangle();
break;
case 'triangle':
shape = new Triangle();
break;
default:
throw new Error(`Invalid shape type: ${type}`);
}
return shape;
}
}
즉, ShapeFactory는 객체 생성을 담당하는 팩토리 클래스이고, ShapeFactory 클래스에는 createShape 메서드가 정의되어 있으며, 사용자가 요청한 타입에 따라 적절한 객체를 생성하여 반환합니다.
팩토리 메서드 패턴
팩토리 메서드 패턴(Factory Method Pattern)은 객체 생성을 추상화한 패턴입니다. 팩토리 메서드 패턴은 객체를 생성하는 부분을 추상화하여, 객체 생성에 대한 의존성을 완화할 수 있습니다. 즉, 객체 생성에 대한 부분을 인터페이스로 분리하고, 객체 생성을 위한 팩토리 메서드를 만듭니다. 이렇게 하면 추상화된 객체를 사용하는 코드와 구체적인 객체 생성 코드를 분리할 수 있습니다.팩토리 메서드 패턴은 사용자 코드와 객체 생성 코드가 결합되어 있지 않으므로, 유지보수성이 좋습니다.
팩토리 메서드 패턴 JavaScript 예제
팩토리 메서드 패턴을 구현하기 위해서는 먼저 팩토리에서 반환할 Product와 Product를 상속하는 두가지 Product를 만듭니다. Product는 팩토리에서 반환할 클래스이고, ConcreteProductA와 ConcreteProductB는 Product 클래스를 상속한 구체적인 제품 클래스입니다.
// Product 인터페이스 정의
class Product {
constructor(name) {
this.name = name;
}
}
// ConcreteProductA 클래스 정의
class ConcreteProductA extends Product {
constructor() {
super('Product A');
}
}
// ConcreteProductB 클래스 정의
class ConcreteProductB extends Product {
constructor() {
super('Product B');
}
}
이제 팩토리 메서드 패턴을 구현하기 위해 해당 Product들을 생성하는 팩토리를 만듭니다. Creator는 제품을 생성하는 팩토리 메서드를 정의하는 클래스이며, ConcreteCreatorA와 ConcreteCreatorB는 Creator 클래스를 상속하여 createProduct 메서드를 구현합니다. createProduct 메서드는 위에서 만든 Product를 반환합니다.
// Creator 클래스 정의
class Creator {
createProduct() {
throw new Error('You have to implement the method createProduct!');
}
}
// ConcreteCreatorA 클래스 정의
class ConcreteCreatorA extends Creator {
createProduct() {
return new ConcreteProductA();
}
}
// ConcreteCreatorB 클래스 정의
class ConcreteCreatorB extends Creator {
createProduct() {
return new ConcreteProductB();
}
}
사용자는 ConcreteCreatorA와 ConcreteCreatorB를 이용하여, 적절한 제품을 생성합니다. ConcreteCreatorA와 ConcreteCreatorB는 Product 클래스의 인스턴스를 생성하는 createProduct 메서드를 제공합니다. 사용자는 이를 호출하여, 적절한 제품을 생성할 수 있습니다.
// Creator 클래스를 사용하는 예제
const creatorA = new ConcreteCreatorA();
const creatorB = new ConcreteCreatorB();
const productA = creatorA.createProduct();
const productB = creatorB.createProduct();
console.log(productA.name); // 'Product A'
console.log(productB.name); // 'Product B'
위와 같이 팩토리 메서드 패턴을 사용하면 객체 생성에 대한 의존성을 완화할 수 있습니다. 객체 생성 코드와 사용자 코드를 분리함으로써 유지보수성을 높일 수 있습니다. 또한 팩토리 메서드 패턴에서 사용자가 이용하는 것은 인터페이스의 함수이기 때문에, 객체 생성 방식을 변경하더라도 Creator을 사용하는 레이어의 코드를 수정할 필요가 없습니다.
추상 팩토리 패턴 (Abstract Factory Pattern)
추상 팩토리 패턴(Abstract Factory Pattern)은 팩토리 클래스(추상 클래스 역할을 하는 클래스)를 구현하는 팩토리를 만들어냅니다. 각각의 팩토리 클래스가 서로 연관되어 있어서, 서로 다른 종류의 객체를 생성할 때 사용합니다.
추상 팩토리 패턴을 사용하면 다양한 종류의 객체를 생성할 수 있으며, 객체 생성에 대한 의존성을 완화 할 수 있습니다. 추상 팩토리 패턴은 팩토리 메소드 패턴과 비슷하게, 객체 생성에 대한 부분을 추상화하여, 객체 생성에 대한 의존성을 완화합니다. 하지만, 팩토리 메소드 패턴이 단일 객체 생성을 추상화하는 것에 반해, 추상 팩토리 패턴은 서로 관련된 객체들을 묶어서 추상화한 팩토리를 만들고, 해당 팩토리를 이용해 객체를 생성합니다.
예를 들어, 우리가 생산하는 자동차에는 엔진, 타이어, 에어백 등 다양한 부품이 있습니다. 각각의 부품을 생산하는 공장이 있다고 가정해봅시다. 이때, 추상 팩토리 패턴을 사용하여, 자동차 생산 공장에서 엔진, 타이어, 에어백 등의 부품을 생산할 수 있습니다. 자동차 공장은 필요한 부품을 요청하면, 해당 부품을 생산하는 공장에서 해당 부품을 제공하는 방식으로 자동차를 생산합니다.
추상 팩토리 패턴을 사용하면, 객체를 생성하는 부분을 인터페이스로 추상화하여, 유연하게 객체를 생성할 수 있습니다. 또한, 객체를 생성하는 부분과 사용하는 부분을 분리할 수 있기 때문에, 유지보수성이 좋아집니다.
추상 팩토리 패턴 JavaScript 예제
추상 팩토리 패턴에는 추상 클래스 역할을 하는 팩토리 객체가 존재합니다. 이 팩토리는 이 팩토리에서는 특정 종류의 객체들을 생성하기 위한 메서드를 가집니다. 따라서 ProductA와 ProductB를 생성하는 추상 팩토리라고 하면 다음과 같이 만들 수 있습니다.
class AbstractFactory {
createProductA() {
throw new Error('You have to implement the method createProductA!');
}
createProductB() {
throw new Error('You have to implement the method createProductB!');
}
}
추상 팩토리는 ConcreteFactory로 구현되며 이 Factory들은 각각 추상 팩토리의 메서드를 구현해 해당 종류의 Product를 만들어냅니다. ProductA1과 ProductA2는 ProductA를 상속하는 클래스이며, ProductB1과 ProductB2는 ProductB를 상속하는 클래스입니다.
// ConcreteFactory1 클래스 정의
class ConcreteFactory1 extends AbstractFactory {
createProductA() {
return new ProductA1();
}
createProductB() {
return new ProductB1();
}
}
// ConcreteFactory2 클래스 정의
class ConcreteFactory2 extends AbstractFactory {
createProductA() {
return new ProductA2();
}
createProductB() {
return new ProductB2();
}
}
팩토리 패턴과 추상 팩토리 패턴의 차이점
팩토리 패턴과 추상 팩토리 패턴은 객체 생성을 처리하는 코드와 사용자 코드를 분리하여 객체를 생성하는 패턴입니다. 하지만, 두 패턴은 다음과 같은 차이점이 있습니다.
1. 객체 생성 대상: 팩토리 패턴은 하나의 객체(특정 클래스를 상속하는 클래스의 인스턴스)를 생성하는 패턴입니다. 반면에 추상 팩토리 패턴은 여러 개의 연관된 객체(ProductA, ProductB 등)를 생성하는 패턴입니다.
2. 객체 생성 방식: 팩토리 패턴은 단순히 객체 생성을 담당하는 팩토리 클래스를 만들어서, 사용자가 요청하는 객체를 생성하는 방식입니다. 반면에 추상 팩토리 패턴은 서로 연관된 객체를 생성하는 부분을 묶어서 추상 팩토리 클래스를 만들고, 해당 추상팩토리 클래스를 구현하는 클래스에서 관련된 객체들을 생성하는 방식입니다.
결론
팩토리 패턴과 추상 팩토리 패턴은 객체 생성에 대한 부분을 추상화하여, 객체 생성에 대한 의존성을 완화 할 수 있는 디자인 패턴입니다. 두 패턴은 객체 생성을 처리하는 코드와 사용자 코드를 분리하여, 객체를 생성하는 방식을 유연하게 변경할 수 있습니다. 또한, 팩토리 패턴과 추상 팩토리 패턴을 사용하면, 객체를 생성하는 부분과 사용하는 부분을 분리할 수 있기 때문에, 유지보수성이 좋아집니다.
팩토리 패턴은 하나의 객체를 생성하는 패턴으로, 객체 생성을 처리하는 코드와 사용자 코드를 분리하여 객체를 생성하는 방식을 유연하게 변경할 수 있습니다. 추상 팩토리 패턴은 여러 개의 연관된 객체를 생성하는 패턴으로, 서로 연관된 객체를 묶어서 팩토리 클래스를 만들고, 해당 팩토리 클래스에서 관련된 객체들을 생성하는 방식입니다.
각각의 패턴은 프로그램의 요구사항에 따라 선택해서 사용하면 됩니다. 팩토리 패턴은 단일 객체 생성에 적합하며, 추상 팩토리 패턴은 여러 개의 연관된 객체를 생성할 때 사용합니다. 따라서, 프로그램의 요구사항을 고려하여 팩토리 패턴과 추상 팩토리 패턴을 적절히 사용하면, 코드의 가독성과 유지보수성을 높일 수 있습니다.
'디자인 패턴' 카테고리의 다른 글
[JavaScript 디자인 패턴] 빌더 패턴: 객체 생성과 표현을 분리하여, 객체 생성 코드를 쉽게 관리할 수 있도록 도와주는 디자인 패턴 (0) | 2023.02.23 |
---|