본문 바로가기
개발/디자인 패턴

[Java 언어로 배우는 디자인 패턴 입문] 인스턴스 만들기 8. Abstract Factory

by hongdor 2021. 1. 9.
728x90

출처 : 책 - java 언어로 배우는 디자인 패턴 입문

 

8. Abstract Factory - 복잡한 인스턴스 조립하기

 

1. 목적

 

 - 부품 인스턴스'들'의 생성을 하위 클래스로 넘긴다.

   > 즉 부품보다 부품의 조립에 집중할 수 있게된다.

 

 - 인스턴스가 1개만 있으면 팩토리 메소드 디자인패턴으로 처리해도 된다.

  > 예시) 키보드 인터페이스에 LG 키보드 or 삼성 키보드 할당

 - 하지만 인스턴스가 여러개인 경우는 인스턴스들을 감싼 팩토리를 만들어

   인스턴스들을 한꺼번에 생성한 후 팩토리를 할당한다.

   > 예시) 키보드 - 삼성 or LG 할당 , 마우스 - 삼성 or LG 할당    (X)

             컴퓨터 - 삼성 or LG 컴퓨터 할당(해당 브랜드 마우스, 키보드 생성은 컴퓨터 인스턴스 안에서 처리) (O)

 - 이렇게 인스턴스들을 생성하는 Factory를 갈아 끼울 수 있도록 한다.

 

 > Factory Method은 하나의 군에 대한 생성하는 정보(Builder 클래스)를 감추는 느낌이 있다면

    Abstract Factory 는 여러 군들에 관한 생성을 감추는 느낌이다.

  (출처: https://hamait.tistory.com/869 [HAMA 블로그])

 

 

2. 예제

 

(1) Main

 > listfactory.Listfactory 를 문자열로 입력한다고 가정.

 > HTML을 생성하는 프로그램이다.

import factory.*;

public class Main {
    public static void main(String[] args) {
        if (args.length != 1) {
            System.out.println("Usage: java Main class.name.of.ConcreteFactory");
            System.out.println("Example 1: java Main listfactory.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 chosun = factory.createLink("조선일보", "http://www.chosun.com/");

        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(chosun);

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

 

 

(2) Factory - 인스턴스들(Link, Tray, Page)을 생성하는 역할

 > classnamfactory = (Factory)Class.forName(classname).newInstance();

 > 문자열 변수(classname)와 일치하는 클래스의 인스턴스를 생성하는 문장이다.

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);
}

 

 

(3) Item - 인스턴스로 만들 클래스들 중 Link, Tray의 인터페이스

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

 

 

(4) Link, Tray, Page,  - 인스턴스로 생성할 클래스들

public abstract class Link extends Item {
    protected String url;
    public Link(String caption, String url) {
        super(caption);
        this.url = url;
    }
}
public abstract class Tray extends Item {
    protected ArrayList tray = new ArrayList();
    public Tray(String caption) {
        super(caption);
    }
    public void add(Item item) {
        tray.add(item);
    }
}
public abstract class Page {
    protected String title;
    protected String author;
    protected ArrayList content = new ArrayList();
    public Page(String title, String author) {
        this.title = title;
        this.author = author;
    }
    public void add(Item item) {
        content.add(item);
    }
    public void output() {
        try {
            String filename = title + ".html";
            Writer writer = new FileWriter(filename);
            writer.write(this.makeHTML());
            writer.close();
            System.out.println(filename + " 을 작성했습니다.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public abstract String makeHTML();
}

 

--------------------------------------------------------------------------------

 

위 Factory와 Link, Tray, Page는 추상클래스 이므로 Main에 입력한 listfactory.Listfactory 구현 클래스가 할당된다.

 

 

(1) ListFactory

package listfactory;

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);
    }
}

 

 

(2) ListLink

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";
    }
}

 

 

(3) ListPage

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

 

 

(4) ListTray

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();
    }
}
728x90

댓글