Factory Method 패턴
Factory Method 패턴은 디자인 타임보다는 런타임 시에 오브젝트의 클래스를 명시하면서, 오브젝트의 생성을 추상화할 수 있게 해준다 오브젝트를 생성하는 별도의 메소드를 별도의 정의를 통해서 추상화를 구현한다. 하위 클래스들은 필요할때마다 생성하게 되는 파생 오브젝트의 타입을 별도로 명시하기 위해서 클래스를 생성하는 메소드를 재정의할 수 있다(필요할 때마다 필요한 것을 생성한다는 의미로 받아들일 수도 있다) 사실 factory라는 단어는 오브젝트의 생성을 주목적으로 하는 임의의 매소드를 참조하기 위해 사용된다
Factory 메소드들은 툴킷이나 프레임워크 같은 곳에서 매우 많이 볼 수 있다. 이러한 곳에서는 많은 라이브러리들이 있게 마련이고, 이 코드들은 프레임워크를 사용하는 프로그램들이 서브 클래스로 사용할 오브젝트들의 타입을 만들어 내야 할 필요가 있다. 이러한 경우는 각각 자신에게 알맞은 오브젝트를 만드는 서로 다른 계층 구조의 오브젝트들이 필요한 병렬 클래스 계층 구조들에서 공통적으로 볼 수 있다
Factory Method 패턴의 중요한 의도는 서브 클래스들이 자신에게 필요한 오브젝트의 타입을 선택하는 것이지만, 오브젝트를 생성하는 팩토리 메소드를 사용한다는 점 이외에도 서브 클래스의 타입들이 서로 의존하지 않는다는 장점이 있다 . 그래서, 이러한 장점들을 얻기 위해 팩토리 매소드들은 여러 의미를 가지지 않도록 단순화 하는 것이 일반적이다
예제를 통해 알아보는 Factory Method 패턴
이 패턴의 궁극적인 목적은 오브젝트의 생성을 캡슐화하는 것이다. 이러한 예를 보여주기 위해서, 20세기 자동차 공장을 만들 것이다. 각각의 Car클래스는 각 서브 클래스마다 독자적인 특징을 할당하기 위해서 재정의도니 팩토리 메소드를 사용할 것이다.
이를 위해서, 먼저 Car 추상 클래스를 다음처럼 만들 것이다
abstract class Car
{
private List<Feature> features = new List<Feature>();
//생성자는 팩토리 메소드를 실행한다.
public Car()
{
this.CreateFeatures();
}
}
//프로퍼티
public List<Feature> Features
{
get{return features;}
}
// 팩토리 메소드를 상속받은 메소드
public abstract void CreateFeatures();
//재정의
public override string ToString()
{
return this.GetType().Name;
}
예제에서 보듯이, Car클래스는 자동차의 특징을 보여주는 프로퍼티를 가지고있다. 이 특징들은 매우 간단하기 때문에, 이를 할당하고 가져오는 로직의 구현보다는 개념에 더 중점을 둘 것이다. 또한, 이러한 개념에 따라 출력하는 내용은 클래스의이름으로 한정할 것이다.
abstract class Feature
{
//재정의. 클래스의 이름을 출력한다.
public override string ToString()
{
return this.GetType().Name;
}
}
또한 , 자동차 공장에서 만들어내는 자동차의 기본 사양은 다음고 ㅏ같다
// 실제 생산되는 품목들
class FourWeels : Feature
{}
class V6Engine : Feature
{}
class V8Engine : Feature
{}
class FourDoors : Feature
{}
class TwoDoors : Feature
{}
class SubRoof : Feature
{}
class AirBags : Feature
{}
class HybridEngine : Feature
{}
이제, 실제 Car 클래스의 서브 클래스들을 만들 것이다. 각 서브 클래스들은 Create Features() 메소드를 재정의한다. 이러한 방식으로, 각 서브클래스들은 Factory Method 패턴의 의미에 부합하도록 자신의 타입에 맞게 자동차의 특징을 조정한다
//실제 클래스를 만들어낸다
class CooperMini : Car
{
// Factory Method의 개념에 맞도록 구현
public ovvverride void void CreateFeatures()
{
Features.Add(new FoureWheels());
Features.Add(new TwoDoors());
Features.Add(new AirBags());
Features.Add(new V6Engine());
Features.Add(new SunRoof());
}
}
class BMWSedan : Car
{
// Factory Method의 개념에 맞도록 구현
public override void CreateFeatures()
{
Features.Add(new FourDoors());
Features.Add(new FourWheels());
Features.Add(new AirBags());
Features.Add(new V8Engine());
Features.Add(new SunRoof());
}
}
class Prius : Car
{
// Factory Method의 개념에 맞도록 구현
public override void CreateFeatures()
{
Features.Add(new TwoDoors());
Featrues.Add(new FourWheels());
Featrues.Add(new HybridEngine());
Features.Add(new AirBags());
Features.Add(new SunRoof());
}
}
class FordExpedition : Car
{
//Factory Method의 개념에 맞도록 구현
pulic override void CreateFeatrues()
{
Features.Add(new FourDoors());
Featrues.Add(new FourWheels());
Featrues.Add(new V8Engine());
Features.Add(new AirBags());
}
}
이렇게 생성될 코드와 이를 출력해볼 코드가 필요하다
다음은 이를 정의한 코드들이다
class Program
{
static void Main()
{
// 주의 : docuemnt 클래스의 생성자가 팩토리 메소드를 호출한다.
List<Car> cars = new List<Car> ();
cars.Add(new CooperMini());
cars.Add(new BMWSedan());
cars.Add(new Prius());
cars.Add(new FordExpedition());
// 문서 페이지를 보여준다.
foreach (Car car in cars)
{
Console.WriteLine(car+ "fully loaded with these features : ");
foreach(Feature feature in car.Features)
{
Console.WriteLine(" " + feature);
}
Console.WriteLine();
}
// 사용자를 기다린다
Console.Read();
}
}
다음은 예제 코드이다
- 참고 Programming .Net 3.5 by Jesse Liberty and Alex Horovitz.