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패턴

'Programming > Design Pattern' 카테고리의 다른 글

[펌] The Singleton Pattern  (0) 2006.01.21
[펌] The Factory Method Pattern  (0) 2006.01.21
[펌] The Singleton Pattern  (0) 2006.01.21
[펌] Chapter 1 Introduction  (0) 2006.01.21
[펌] Chapter 2 객체 지향 기술의 이해  (0) 2006.01.21

Posted by 영웅기삼
,