2011년 5월 22일 일요일

The Abstract Factory Pattern

2. The Abstract Factory Pattern
Abstract Factory 패턴은 서로 밀접하게 관련된 객체들 또는 별로 연관되지 않는 객체들의 패밀리(family)를 생성할 때 그들의 클래스가 무엇인지 구체적으로 알지 않고도 해당되는 객체들을 생성할 수 있는 인터페이스를 제공한다.
Abstract Factory 패턴은 객체들을 집단적으로 생성할 때 사용하는 패턴으로서 실제 반환되는 객체의 클래스 타입을 알 필요가 없이 원하는 객체를 생성하는 인터페이스를 제공한다. 이 인터페이스를 객체를 만드는 공장(factory)라고 부른다.
Abstract Factory 패턴은 Factory Method 패턴보다 더 추상화한 단계이다. 이 패턴은 연관된 객체의 여러 클래스들 중의 하나를 반환하고자 할 때 사용할 수 있다. 즉, Abstract Factory는 여러 팩토리들 중의 하나를 반환하는 팩토리 객체이다. Abstract Factory의 고전적인 응용중의 하나는 컴퓨터시스템이 다중의 "룩앤필(look-and-feel)"을 지원하는 경우에서의 사용이다.
추상적인 공장에서 추상적인 부품을 조립하여 추상적인 제품을 만든다.
구조
*


역할
v AbstractFactory의 역할
객체를 생성하는 인터페이스를 집단적으로 선언한다. 즉, 클라이언트가 사용할 객체를 생성하는 FactoryMethod들을 선언한다. 이 메소드는 Product를 반환한다. 이때 FactoryMethod 메소드는 생성해야 할 객체의 종류별로 여러 개가 존재할 수 있다.
v SpecificFactory의 역할
AbstractFactory를 상속받아 FactoryMethod를 오버라이딩하여 Product클래스를 상속받는 SpecificProduct객체를 생성하는 코드를 구현한다.
v Product의 역할
클라이언트가 사용할 객체의 타입, SpecificFactory에서 생성된 실제 객체는 본 클래스의 하위 클래스의 SpecificProduct 객체이다.
v SpecificProduct의 역할
SpecificFacoty에 의해 실제로 생성되는 객체이다. Product 클래스를 상속받는다.
의도
서로 밀접하게 관련된 객체들 또는 별로 연관되지 않는 객체들의 패밀리(Family)를 생성할 때 그들의 클래스가 무엇인지 구체적으로 알 필요 없이 해당하는 객체를 생성할 수 있는 인터페이스를 제공한다.
적용시기
연관된 여러 객체를 한번에 생성하여 그들을 사용하고 싶을 때 사용할수 있다.
효과
클라이언트 코드가 어떤 종류의 객체인지 구체적으로 알 필요 없이 특정 객체를 생성하여 실제 사용할 때 적용한다. 그러면 클라이언트 코드는 Product객체의 타입을 알필요가 없으므로 추후 Product 객체의 종류가 변경되었을 때에 코드를 수정하는 범위가 최소화 된다.
Abstract Factory는 다음과 같은 문제점을 내포하고 있다.
새로운 산물을 지원하는 것이 어렵다. Abstract factory들을 확장해서 새로운 산물을 생성하는 것은 쉽지 않다. 왜냐하면 AbstractFactory 인터페이스는 생산되어질 산물의 집합을 고정해놓기 때문이다. 새로운 산물을 지원하는 데는 factory의 인터페이스를 확장할 필요가 있다 (AbstractFactory 클래스와 모든 서브 클래스들을 바꾸는것을 포함해서).


예제소스
*


다음은 예제소스이다.
Abfactory 패키지
package abfactory;
public abstract class Item {
protected String caption;
public Item(String caption) {
this.caption = caption;
}
public abstract String makeHTML();
}
package abfactory;
public abstract class Link extends Item {
protected String url;
public Link(String caption, String url) {
super(caption);
this.url = url;
}
}
package abfactory;
import java.util.*;
public abstract class Tray extends Item {
protected ArrayList tray;
public Tray(String caption) {
super(caption);
tray = new ArrayList();
}
public void add(Item item) {
tray.add(item);
}
}
package abfactory;
import java.io.*;
import java.util.ArrayList;
public abstract class Page {
protected String title;
protected String author;
protected ArrayList content;
public Page(String title, String author) {
this.title = title;
this.author = author;
content = new ArrayList();
}
public void output() {
try {
Writer writer = new FileWriter(title+".html");
writer.write(this.makeHTML());
writer.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
public void add(Item item) {
content.add(item);
}
/**
* 템플릿 메소드
* @return
*/
public abstract String makeHTML();
}
package abfactory;
public abstract class Factory {
public static Factory getFactory(String classname) {
Factory factory = null;
try {
factory = (Factory)Class.forName(classname).newInstance();
} catch (ClassNotFoundException e) {
System.err.println("클래스 " + classname + " 이 발견되지 않습니다.");
} catch (Exception e) {
e.printStackTrace();
}
return factory;
}
public abstract Link createLink(String caption, String url);
public abstract Tray createTray(String caption);
public abstract Page createPage(String title, String author);
}


Listfactory 패키지
package listfactory;
import abfactory.Link;
public class ListLink extends Link {
public ListLink(String caption, String url) {
super(caption, url);
}
public String makeHTML() {
return " <li><a href="" + url + "">" + caption + "</a></li>n";
}
}
package listfactory;
import abfactory.Item;
import abfactory.Tray;
import java.util.Iterator;
public class ListTray extends Tray {
public ListTray(String caption) {
super(caption);
}
public String makeHTML() {
StringBuffer buffer = new StringBuffer();
buffer.append("<li>n");
buffer.append(caption + "n");
buffer.append("<ul>n");
Iterator it = tray.iterator();
while (it.hasNext()) {
Item item = (Item)it.next();
buffer.append(item.makeHTML());
}
buffer.append("</ul>n");
buffer.append("</li>n");
return buffer.toString();
}
}
package listfactory;
import abfactory.Item;
import abfactory.Page;
import java.util.Iterator;
public class ListPage extends Page {
public ListPage(String title, String author) {
super(title, author);
}
public String makeHTML() {
StringBuffer buffer = new StringBuffer();
buffer.append("<html><head><title>" + title + "</title></head>n");
buffer.append("<body>n");
buffer.append("<h1>" + title + "</h1>n");
buffer.append("<ul>n");
Iterator it = content.iterator();
while (it.hasNext()) {
Item item = (Item)it.next();
buffer.append(item.makeHTML());
}
buffer.append("</ul>n");
buffer.append("<hr><address>" + author + "</address>");
buffer.append("</body></html>n");
return buffer.toString();
}
}
package listfactory;
import abfactory.Factory;
import abfactory.Link;
import abfactory.Page;
import abfactory.Tray;
public class ListFactory extends Factory {
public Link createLink(String caption, String url) {
return new ListLink(caption, url);
}
public Tray createTray(String caption) {
return new ListTray(caption);
}
public Page createPage(String title, String author) {
return new ListPage(title, author);
}
}


tablefactory 패키지
package tablefactory;
import abfactory.Link;
public class TableLink extends Link {
public TableLink(String caption, String url) {
super(caption, url);
}
public String makeHTML() {
return "<td><a href="" + url + "">" + caption + "</a></td>n";
}
}
package tablefactory;
import abfactory.Item;
import abfactory.Tray;
import java.util.Iterator;
public class TableTray extends Tray {
public TableTray(String caption) {
super(caption);
}
public String makeHTML() {
StringBuffer buffer = new StringBuffer();
buffer.append("<td>");
buffer.append("<table width="100%" border="1"><tr>");
buffer.append("<td bgcolor="#cccccc" align="center" colspan=""+ tray.size() + ""><b>" + caption + "</b></td>");
buffer.append("</tr>n");
buffer.append("<tr>n");
Iterator it = tray.iterator();
while (it.hasNext()) {
Item item = (Item)it.next();
buffer.append(item.makeHTML());
}
buffer.append("</tr></table>");
buffer.append("</td>");
return buffer.toString();
}
}
package tablefactory;
import abfactory.Item;
import abfactory.Page;
import java.util.Iterator;
public class TablePage extends Page {
public TablePage(String title, String author) {
super(title, author);
}
public String makeHTML() {
StringBuffer buffer = new StringBuffer();
buffer.append("<html><head><title>" + title + "</title></head>n");
buffer.append("<body>n");
buffer.append("<h1>" + title + "</h1>n");
buffer.append("<table width="80%" border="3">n");
Iterator it = content.iterator();
while (it.hasNext()) {
Item item = (Item)it.next();
buffer.append("<tr>" + item.makeHTML() + "</tr>");
}
buffer.append("</table>n");
buffer.append("<hr><address>" + author + "</address>");
buffer.append("</body></html>n");
return buffer.toString();
}
}
package tablefactory;
import abfactory.Factory;
import abfactory.Link;
import abfactory.Page;
import abfactory.Tray;
public class TableFactory extends Factory {
public Link createLink(String caption, String url) {
return new TableLink(caption, url);
}
public Tray createTray(String caption) {
return new TableTray(caption);
}
public Page createPage(String title, String author) {
return new TablePage(title, author);
}
}


클라이언트 프로그램
import abfactory.Factory;
import abfactory.Link;
import abfactory.Page;
import abfactory.Tray;
public class mainClass {
public static void main(String[] args) {
if (args.length != 1) {
System.out.println("Usage: java mainClass [Factory 클래스명]");
System.out.println("Example : java mainClass listfactory.ListFactory");
System.exit(0);
}
Factory factory = Factory.getFactory(args[0]);
Link joins = factory.createLink("중앙일보", "http://www.joins.com/");
Link hani = factory.createLink("한계레 신문", "http://www.hani.co.kr/");
Link us_yahoo = factory.createLink("Yahoo!", "http://www.yahoo.com/");
Link kr_yahoo = factory.createLink("Yahoo!Korea", "http://www.yahoo.co.kr/");
Link excite = factory.createLink("Excite", "http://www.excite.com/");
Link google = factory.createLink("Google", "http://www.google.com/");
Tray traynews = factory.createTray("신문");
traynews.add(joins);
traynews.add(hani);
Tray trayyahoo = factory.createTray("Yahoo!");
trayyahoo.add(us_yahoo);
trayyahoo.add(kr_yahoo);
Tray traysearch = factory.createTray("서치 엔진");
traysearch.add(trayyahoo);
traysearch.add(excite);
traysearch.add(google);
Page page = factory.createPage("LinkPage", "홍길동");
page.add(traynews);
page.add(traysearch);
page.output();
}
}


관련패턴
  • Factory Method 패턴
  • Builder 패턴

댓글 없음:

댓글 쓰기

ETL 솔루션 환경

ETL 솔루션 환경 하둡은 대용량 데이터를 값싸고 빠르게 분석할 수 있는 길을 만들어줬다. 통계분석 엔진인 “R”역시 하둡 못지 않게 관심을 받고 있다. 빅데이터 역시 데이터라는 점을 볼때 분산처리와 분석 그 이전에 데이터 품질 등 데이...