[패턴 정보] 예제로 설명한 Factory Method Pattern

Posted 2005. 9. 27. 10:15 by alice201405
Factory Method 패턴의 워크플로우


객체 지향 프로그램에서 계속해서 볼 수 있는 패턴 중의 하나는 Factory 패턴 또는 클래스이다. Factory 패턴은 제공된 데이터에 의존하는 여러 가능한 클래스 중의 하나를 반환하는 것이다. 일반적으로 반환되는 모든 클래스는 공통적인 부모 클래스와 공통적인 메소들을 가지지만, 그것들은 각각은 다른 일을 하고, 다른 종류의 데이터를 위해 최적화 되어진다. 그림에서 x는 상위 클래스이고 xy와 xz는 x로 부터 파생되었다. Factory는 입력된 인자에 의존하여 하위 클래스를 반환을 결정하는 클래스이다. 오른쪽에서 어떤 abc라는 값이 주어질 때의 getClass 메소드를 정의하였고, 이 메소드는 클래스 x의 인스턴스를 반환한다. 모두 같은 메소드를 가지고 있기 때문에 반환되는 getClass가 어떤 값을 반환하는가는 문제가 되지 않지만, 구현은 다르다. 어떻게 반환할 것인가를 결정하는 것은 전반적으로 Factroy에 의해서 이다.

구조


역할
1. Product(제품)의 역할
생성된 제품(인스턴스)가 가지고 있어야 할 인터페이스(API)를 결정하는 추상 클래스 구체적인 역할은 하위 클래스인 SpecificProduct 역할이 결정한다.

2. Creator(생산자)의 역할
Product 클래스를 생성하는 추상 클래스 Creator는 실제 제품을 생성하는 일을 하는 SpecificCreator 역할에 대해서는 아무것도 모른다.

3. SpecificProduct(구체적 제품)의 역할
구체적인 제품을 나타내는 클래스

4. SpecificCreator(구체적 생산자)의 역할
구체적인 제품을 만드는 클래스



의도

객체를 생성하는 인터페이스를 따로 정의한다. 그리고 생성되는 객체의 클래스를 결정하는 것은 하위 클래스에서 담당한다. 이 패턴은 어떤 클래스가 객체를 생성하는 일을 하위 클래스에게 위임한다.

적용시기
다음과 같은 상황에서 Factory 패턴을 고려할 수 있다.

1. 객체들에 대한 클래스의 종류를 예상 할 수 없을 때
2. 생성할 객체를 기술하는 책임을 서브클래스에 정의하고자 하는 경우
3. 객체 생성의 책임을 서브클래스에서 위임시키고 서브클래스에 대한 정보를 은닉하고자 하는 경우

예제소스


위 예제 소스의 내용은 클라이언트가 사용하는 UI형태가 KoreaUI, EnglandUI두 가지 형태가 있으며 각 UI에서는 htmlPrinter, textPrinter 두 가지 타입의 출력 양식을 가진다.

Printer 클래스는 구성에서 “Product”에 해당하며 UI 클래스는 “Creator”에 해당한다. \

Factory Mothod는 “getPrinter (String message, String textMode)”이다.

다음은 예제소스이다.
=================================================================
product 패키지
=================================================================
[CODE]package product; public class Printer { protected String message; public Printer() { } public String print() { return message; } } package product; public class htmlPrinter extends Printer { public htmlPrinter(String message) { super.message = "      "+message+"      "; } } package product; public class textPrinter extends Printer { public textPrinter(String message) { super.message = "\n "+message+" \n"; } }[/CODE]

=================================================================
creator 패키지
=================================================================

[CODE]package concrete; import product.*; public abstract class UI { protected String header; protected String footer; protected String DecoTitle; public UI(String title) { DecoTitle = title; } protected void setHeader() { header = "Start Print...... "+DecoTitle; } protected void setFooter() { footer = DecoTitle+"........ End Print"; } public String print(String message, String textMode) { setHeader(); setFooter(); StringBuffer buffer = new StringBuffer(); buffer.append(header); buffer.append(getPrinter(message, textMode).print()); buffer.append(footer); return buffer.toString(); } public abstract Printer getPrinter(String message, String textMode); } package concrete; import product.*; import product.Printer; public class KoreaUI extends UI { public KoreaUI(String title) { super(title); } public Printer getPrinter(String message, String textMode) { if(textMode.toUpperCase().equals("HTML")) return new htmlPrinter(message+" 대한민국"); else return new textPrinter(message+" 대한민국"); } } package concrete; import product.*; import product.Printer; public class England extends UI { public England(String title) { super(title); } public Printer getPrinter(String message, String textMode) { if(textMode.toUpperCase().equals("HTML")) return new htmlPrinter(message+" England"); else return new textPrinter(message+" England"); } }[/CODE]


=================================================================
클라이언트 프로그램
=================================================================

[CODE]import concrete.*; public class mainClass { UI ui = null; public mainClass() { } public void setUI(String title, String contry) { if(contry.toUpperCase().equals("KOREA")) ui = new KoreaUI(title); else if(contry.toUpperCase().equals("ENGLAND")) ui = new England(title); } public void exec(String message, String textMode) { System.out.println(ui.print(message, textMode)); } /** * * @param args */ public static void main(String[] args) { mainClass client = new mainClass(); if(args.length != 4) { System.out.println("예) java mainClass [타이틀] [출력메세지] [korea or england] [html or text]"); System.exit(0); } client.setUI(args[0], args[2]); client.exec(args[1], args[3]); } }[/CODE]

=================================================================
관련패턴

1. Factory Method 패턴은 Template Method 패턴에서 발전된 형태이다.
2. Abstract Factory, Builder 패턴에서 참조