2015년 10월 16일 금요일

클래스 디자인 패턴 15. Abstract Factory Pattern

1. 개념
  1) 의미
     interface를 가져와 실제로 구현을 하여 사용하는 Factory 패턴의
      확장입니다.
 

2. 소스

  1) html 페이지를 하나 작성할건데 기존처럼 단순하게
      하는 대신에 작성하는 페이지 위에 추상 클래스를 작성합니다.
      여기서는 구현부에 들어가는 각 부분을
      추상클래스로 하나의 셋트를 작성합니다.

package factory;

public abstract class Item {
protected String caption;
public Item(String caption){
this.caption=caption;
}
public abstract String makeHTML();
}


package factory;

public abstract class Link extends Item{
protected String url;
public Link(String caption, String url){
super(caption);
this.url=url;
}
}


package factory;

import java.util.Vector;

public abstract class Tray extends Item {
protected Vector tray = new Vector();
public Tray(String caption){
super(caption);
}
public void add(Item item){
tray.add(item);
}
}

package factory;

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Vector;

public abstract class Page {
protected String title;
protected String author;
protected Vector content = new Vector<>();

public Page(String title, String author){
this.title=title;
this.author=author;
}

public void add(Item item){
content.add(item);
}
public void output(){
String filename = title +".html";
try {
Writer writer = new FileWriter(filename);
writer.write(this.makeHTML());
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(filename +"을 작성햇습니다.");
}
public abstract String makeHTML();
}

package factory;

public abstract class Factory {
public static Factory getFactory(String classname){
Factory factory = null;
try {
factory = (Factory) Class.forName(classname).newInstance();
} catch (Exception e) {
System.out.println("class is : "+classname +" 이 발견되지 않았습니다.");
}
return factory;
}
public abstract Link createLink(String cpation, String url);
public abstract Tray createTray(String caption);
public abstract Page createPage(String title, String author);
}


  2) 이를 사용해서 test를 진행할 main 클래스를 작성합니다.
       이후 에러는 나지 않지만 실행시 클래스가 없다고 나옵니다.
       현재 구현한 부분은 실행되지 않는 추상적인 부분밖에 없어서
       그렇습니다.

package noname;

import factory.Factory;
import factory.Link;
import factory.Page;
import factory.Tray;

public class MainTest {
public static void main(String[] args) {
if(args.length!=1){
System.out.println("Usage : Java main class.name.of.ConcreateFactory");
System.out.println("example 1:  java main listfacoty.ListFActory");
System.out.println("example 2:  java main tableFactory.TableFactory");
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("newspaper");
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", "kim kmi kkim");
page.add(traynews);
page.add(traysearch);
page.output();
}
}


  3) 지금까지 작성한 추상클래스를 상속받아 아래와 같이
      구현 클래스를 작성합니다.
       ListFactory 클래스는 factory에서 지정한 함수에서
       각자 추상 클래스를 상속받은 인스턴스를 생성해서
       넘겨주는 역할을 합니다.

package listfactory;

import factory.Factory;
import factory.Link;
import factory.Page;
import factory.Tray;

public class ListFactory extends Factory {

@Override
public Link createLink(String cpation, String url) {
return new ListLink(cpation, url);
}

@Override
public Tray createTray(String caption) {
return new ListTray(caption);
}

@Override
public Page createPage(String title, String author) {
return new ListPage(title, author);
}
}




  4) 각 추상클래스를 상속받아 실제 코드를 기입한
      부분입니다.
package listfactory;

import factory.Link;

public class ListLink extends Link {

public ListLink(String caption, String url) {
super(caption, url);
}

@Override
public String makeHTML() {
return "<li><a href=\""+url+"\">"+caption+"</a></li>\n";
}
}


package listfactory;

import java.util.Iterator;

import factory.Item;
import factory.Tray;

public class ListTray extends Tray {

public ListTray(String caption) {
super(caption);
}

@Override
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 java.util.Iterator;

import factory.Item;
import factory.Page;

public class ListPage extends Page {

public ListPage(String title, String author) {
super(title, author);
}

@Override
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();
}
}




결과 : 실행시 argument 에 listfactory/ListFactory 를 넣어준다.
         콘솔로 실행시에는 java listfactory/ListFactory.java
         를 넣어줘야 정상적으로 실행된다.

LinkPage.html을 작성햇습니다.


해당 파일 실행시 다음 결과를 확인 할 수 있습니다.
   여기서 중요한 점은 추상 클래스 셋트를 상속하여
   다른 구현 클래스를 추가시에 다른 소스 변동없이 다른
   페이지 구성을 할 수가 있습니다.

LinkPage

  • newspaper >
  • 서치엔진 >

  • kim kmi kkim



    3. 다이어그램


    4. 관련패턴
      1) Builder 패턴
          인터페이스가 정해져 있는 추상적인 부품을 구현해 나가는 형태이며
          Builder 패턴은 단계를 밟아나가면서 대규모의
          인스턴스를 만들어 나갑니다.

      2) Factory Method 패턴
          제품, 부품을 만드는 형태는 Factory Method와 같습니다.

      3) Composite 패턴
          만들어진 결과물은 Composite 패턴이 되는 경우가 있습니다.

      4) Singleton 패턴
          구체정인 공장은 Singleton 패턴이 되는 경우가 있습니다.

    댓글 없음:

    댓글 쓰기