목차
팩토리 메서드(Factory Method)
팩토리 메서드 패턴은 생성 디자인 패턴에 속한다. 이 패턴의 목적은 객체 생성 처리를 서브클래스에 위임하여 부모 클래스에서는 어떤 클래스의 인스턴스를 생성할지에 대한 결정을 하지 않도록 하는 것이다. 즉, 객체 생성 코드를 전체 프로그램 코드와 분리하여 유연성을 높이고, 코드의 관리를 용이하게 한다.
패턴의 이름은 "공장(Factory)"이라는 단어에서 유래했다. 실제 공장에서 제품을 만들듯, 팩토리 메서드 패턴에서는 객체를 생성하는 '공장' 역할을 하는 메서드를 제공한다. 이 패턴을 사용함으로써, 객체 생성 과정을 서브클래스에게 맡기고, 클라이언트 코드는 추상화된 인터페이스를 통해 원하는 객체를 얻게 된다.
패턴 미적용 예시 코드
// 패턴 미적용 상황: 클라이언트 코드가 직접 구체적인 클래스를 생성한다.
public class Client
{
public void Main()
{
// 직접 구체 클래스를 생성
Product product = new ConcreteProductA();
Console.WriteLine(product.Operation());
}
}
public abstract class Product
{
public abstract string Operation();
}
public class ConcreteProductA : Product
{
public override string Operation()
{
return "ConcreteProductA의 연산";
}
}
public class ConcreteProductB : Product
{
public override string Operation()
{
return "ConcreteProductB의 연산";
}
}
이 코드에서는 Client 클래스가 ConcreteProductA를 직접 생성하고 있다. 만약 Product를 상속받는 다른 클래스를 생성하고, Client가 그 클래스의 인스턴스를 생성해야 한다면, Client 코드를 수정해야 한다. 이는 확장성과 유지보수성에 좋지 않다.
패턴 적용 예시 코드
public abstract class Creator
{
// 팩토리 메서드 선언
public abstract Product FactoryMethod();
public string SomeOperation()
{
// 팩토리 메서드를 호출해 제품 객체를 생성한다.
var product = FactoryMethod();
// 제품 객체를 사용한 연산을 수행한다.
return $"Creator: 동일한 제작자의 코드가 작동하고, {product.Operation()}";
}
}
public class ConcreteCreatorA : Creator
{
// ConcreteProductA 객체를 생성하는 구체적인 팩토리 메서드
public override Product FactoryMethod()
{
return new ConcreteProductA();
}
}
public class ConcreteCreatorB : Creator
{
// ConcreteProductB 객체를 생성하는 구체적인 팩토리 메서드
public override Product FactoryMethod()
{
return new ConcreteProductB();
}
}
public abstract class Product
{
public abstract string Operation();
}
public class ConcreteProductA : Product
{
public override string Operation()
{
return "ConcreteProductA의 연산";
}
}
public class ConcreteProductB : Product
{
public override string Operation()
{
return "ConcreteProductB의 연산";
}
}
public class Client
{
public void Main()
{
// Creator의 서브클래스 인스턴스 생성
Console.WriteLine("App: Launched with the ConcreteCreatorA.");
ClientCode(new ConcreteCreatorA());
Console.WriteLine("");
Console.WriteLine("App: Launched with the ConcreteCreatorB.");
ClientCode(new ConcreteCreatorB());
}
// 클라이언트 코드는 Creator 클래스의 인스턴스에 대해 동일하게 동작한다.
public void ClientCode(Creator creator)
{
// ...
Console.WriteLine($"Client: 나는 모르지만, Creator 클래스가 {creator.SomeOperation()} 결과를 생성했다.");
}
}
패턴을 적용한 코드에서는 Creator 라는 추상 클래스에서 객체 생성의 책임을 FactoryMethod라는 추상 메서드로 정의하고, 이 메서드의 구현은 구체적인 Creator 서브클래스인 ConcreteCreatorA와 ConcreteCreatorB에서 이루어진다. 각각의 구체적인 생성자 클래스는 Product 타입의 객체를 반환하는 FactoryMethod를 오버라이드하여 구체적인 제품 객체를 생성한다.
이 접근 방식의 핵심 이점은, 클라이언트 코드가 구체 클래스를 직접 생성하는 대신, 생성을 위한 메서드를 호출함으로써 객체 생성 로직과 클라이언트 코드 사이의 의존성을 줄인다는 것이다. 이로써 클라이언트 코드는 구체적인 제품 클래스가 변경되거나, 추가되어도 변경할 필요가 없어진다. 즉, 확장성과 유지보수성이 향상된다.
패턴을 적용하지 않았을 때의 문제점
패턴 미적용 예시에서 볼 수 있듯이, 클라이언트가 구체적인 Product 클래스를 직접 생성하는 경우, 다음과 같은 문제점이 발생할 수 있다:
- 확장성 저하: 새로운 Product 서브클래스를 추가할 때마다, 해당 서브클래스를 생성하는 클라이언트 코드도 함께 변경해야 한다.
- 코드 중복: 다양한 클라이언트가 동일한 방식으로 특정 Product 서브클래스의 인스턴스를 생성하는 경우, 코드 중복이 발생할 수 있다.
- 유지보수 어려움: 생성 로직이 클라이언트 코드에 분산되어 있어, 객체 생성 방식을 변경하고자 할 때 모든 클라이언트 코드를 찾아 수정해야 하는 번거로움이 있다.
팩토리 메서드 패턴을 적용함으로써, 이러한 문제들을 해결할 수 있다. 객체의 생성을 캡슐화함으로써, 클라이언트 코드와 생성되는 객체 사이의 결합도를 낮추고, 코드의 유연성 및 확장성을 향상시킬 수 있다.
Abstract Factory vs Factory Method
Abstract Factory와 Factory Method는 모두 생성 패턴에 속하지만, 구체적인 용도와 구현 방식에서 차이가 있다.
Factory Method 패턴
- 목적: 객체 생성을 서브클래스에 위임하여, 부모 클래스에서는 어떤 클래스의 인스턴스를 생성할지에 대한 결정 없이 객체를 생성할 수 있도록 하는 것.
- 구현: **Factory Method**는 하나의 메서드로, 이 메서드가 새로운 객체를 생성하여 반환한다. 이 패턴은 클래스 확장을 통해 객체 생성을 처리하며, 생성할 객체의 클래스를 바꾸고 싶을 때는 해당 객체를 생성하는 클래스를 상속받아 팩토리 메서드를 오버라이딩한다.
- 사용 시점: 특정 클래스의 인스턴스를 생성하는 방법을 서브클래스가 결정하게 하고 싶을 때 사용한다.
Abstract Factory 패턴
- 목적: 관련된 여러 종류의 객체를 생성하기 위한 인터페이스를 제공하며, 구체적인 클래스는 클라이언트로부터 분리된다.
- 구현: 이 패턴은 여러 팩토리 메서드로 구성된 인터페이스(또는 추상 클래스)를 사용하여, 서로 관련이 있거나 의존적인 여러 객체의 그룹을 생성한다. 클라이언트는 인터페이스를 통해 구체적인 팩토리를 사용하며, 구체적인 팩토리는 그 인터페이스를 구현하고 여러 종류의 객체를 생성한다.
- 사용 시점: 클라이언트가 특정 그룹의 서로 관련된 여러 객체를 생성해야 할 때, 그리고 구체적인 클래스에 대한 정보 없이도 이들을 생성할 수 있도록 하고 싶을 때 사용한다.
차이점 요약
- 목적과 범위의 차이: Factory Method는 객체 생성을 서브클래스가 결정하게 하는 것에 중점을 둔 반면, Abstract Factory는 관련된 객체의 그룹을 생성할 수 있는 인터페이스를 제공하는 데 중점을 둔다.
- 구현 방식: Factory Method는 하나의 메서드를 통해 객체를 생성하는 반면, Abstract Factory는 관련된 여러 객체를 생성할 수 있는 여러 메서드(또는 객체)를 제공한다.
- 사용하는 상황: Factory Method는 생성할 객체의 종류가 많지 않지만, 그 생성 과정에 변화를 주고 싶을 때 유용하다. 반면, Abstract Factory는 서로 관련된 여러 객체의 그룹을 일관되게 생성해야 할 때 더 적합하다.
'컴퓨터 과학 > 디자인패턴' 카테고리의 다른 글
[디자인패턴] 생성 패턴(5) : 프로토타입(Prototype) (0) | 2024.03.24 |
---|---|
[디자인패턴] 생성 패턴(4) : 빌더(Builder) (0) | 2024.03.24 |
[디자인패턴] 생성 패턴(2) : 추상 팩토리(Abstract Factory) (1) | 2024.03.24 |
[디자인패턴] 생성 패턴(1) : 심플 팩토리(Simple Factory) (0) | 2024.03.24 |
[디자인 패턴] 디자인 패턴의 역사와 종류 (0) | 2024.03.24 |