참고 : JAVA 언어로 배우는 디자인 패턴 입문
Template Method 패턴에서는 상위 클래스에서 처리의 골격을 만들고, 하위 클래스에서 구체적인 처리의 내용을 만들었습니다.
이 패턴을 인스턴스 생성에 적용한 것이 Factory Method 패턴입니다.
인스턴스를 생성하는 공장을 Template Method 패턴으로 구성한 것이 Factory Method 패턴이 됩니다.
Factory Method 패턴에서는 인스턴스를 만드는 방법을 상위 클래스 측에서 결정하지만 구체적인 클래스 이름까지는 결정하지 않습니다.
구체적인 내용은 모두 하위 클래스 측에서 수행합니다. 따라서 인스턴스 생성을 위한 골격(Framework)과
실제의 인스턴스 생성의 클래스를 분리해서 생각할 수 있습니다.
// 추상 메소드 user만 정의되어 있는 추상 클래스
public abstract class Product {
public abstract void use();
}
// 메소드 create을 구현하고 있는 추상 클래스
public abstract class Factory {
// Template Method 패턴
public final Product create(String owner) {
Product p = createProduct(owner);
registerProduct(p);
return p;
}
protected abstract Product createProduct(String owner);
protected abstract void registerProduct(Product p);
}
// 메소드 use를 구현하고 있는 클래스
public class IDCard extends Product {
private String owner;
public IDCard(String owner) {
System.out.println(owner + "의 카드를 만듭니다.");
this.owner = owner;
}
@Override
public void use() {
System.out.println(owner + "의 카드를 사용합니다.");
}
public String getOwner() {
return owner;
}
}
// 메소드 createProduct, registerProduct를 구현하고 있는 클래스
public class IDCardFactory extends Factory {
private List owners = new ArrayList();
@Override
protected Product createProduct(String owner) {
return new IDCard(owner);
}
@Override
protected void registerProduct(Product product) {
owners.add(((IDCard)product).getOwner());
}
public List getOwner() {
return owners;
}
}
public class Main {
public static void main(String[] args) {
Factory factory = new IDCardFactory();
Product card1 = factory.create("홍길동");
Product card2 = factory.create("이순신");
Product card3 = factory.create("강감찬");
card1.use();
card2.use();
card3.use();
}
}
이 예제 프로그램에서는 ID카드를 만드는 공장을 소재로 하였습니다. 다섯 개의 클래스가 있습니다. Product 클래스와 Factory 클래스가 인스턴스 생성을 위한 골격(Framework)의 역할을 합니다. IDCard 클래스와 IDCardFactoty 클래스는 구체적인 내용을 구현하며 idcard라는 패키지에 속해 있습니다.
Factory 클래스에서는 Template Method 패턴이 사용되고 있습니다. 추상 메소드 createProduct 에서는 '제품을 만들고', 만든 제품을 추상 메소드 registerProduct 에서 '등록'합니다. '제품을 만들고', '등록'하는 구현은 하위 클래스에서 수행합니다. 이 Framework에서 공장이란 'create 메소드에서 Product의 인스턴스를 생성하는 것'으로 규정하고 있습니다. 그리고 create 메소드는 'createProduct 에서 제품을 만들어서 registerProduect 에서 등록한다' 라는 순서로 구현하고 있습니다.
추상적인 골격과 구체적인 내용의 두가지 측면에서 보면 각각 framework 패키지와 idcard 패키지로 나뉘어 있습니다. 여기에서 동일한 Framework를 사용해서 전혀 다른 '제품'과 '공장'을 만든다고 가정해보겠습니다. 예를 들어, TV의 클래스 Television과 TV공장 TelevisionFactory 를 만든다고 한다면 이런 경우 Framework 패키지의 내용을 수정하지 않아도 전혀 다른 제품과 공장을 만들 수 있습니다. 즉, Framework 패키지의 내용을 수정할 필요는 없습니다.
[추가]
예제에서 Factory 클래스의 createProduct 메소드는 추상 메소드이며, 하위 클래스에서 구현하게 됩니다. createProduct 메소드의 기술 방법은 다음과 같이 세가지로 생각할 수 있습니다.
1. 추상 메소드로 한다.
추상 메소드로 하면 하위 클래스는 반드시 이 메소드를 구현해야 합니다. 구현되어 있지 않으면 컴파일할 때 검출됩니다.
예제 프로그램에서는 이 방법을 이용하고 있습니다.
abstract class Factory {
public abstract Product createProduct(String name);
…
}
2. 디폴트의 구현을 준비해 둔다.
디폴트의 구현을 준비해 두고 하위 클래스에서 구현하지 않았을 때 사용하면 됩니다.
class Factory {
public Product createProduct(String name) {
return new Product(name);
}
...
}
단, 이 경우에는 Product 클래스에 대해서 직접 new를 이용하고 있으므로 Product 클래스를 추상 클래스로 둘 수 없습니다.
3. 에러를 이용한다.
class Factory {
Public Product createProduct(String name) {
Throw new FactoryMethodRuntimeException();
}
}
FactoryMethodRuntimeException 은 별도로 작성되어 있다고 가정합니다.