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

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

by hongdor 2021. 1. 8.
728x90

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

 

7. Builder - 복잡한 인스턴스 조립하기

 

 

1. 목적

 

 - 생성 기능을 갖는 클래스(Builder)와 동작하는 클래스(Director)를 분리 한다.

 - 의도 : 동작 클래스에 생성 클래스를 주입해준 후 따로 필요한 인스턴스들을 생성하고 동작클래스를 사용한다.


 > Builder 패턴은 하나의 군에 대한 생성하는 정보(Builder 클래스)를 감추는 느낌도 있다.

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

 

 

 

2. 예제

 

(1) Director - 동작 클래스

public class Director {
    private Builder builder;
    public Director(Builder builder) {        // Builder의 Subclass의 인스턴스가 주어지므로
        this.builder = builder;             // builder 필드에 저장해 둔다.
    }
    public void construct() {               		// 문서구축
        builder.makeTitle("Greeting");              // 타이틀
        builder.makeString("아침과 낮에");         // 문자열
        builder.makeItems(new String[]{            // 개별항목
            "좋은 아침입니다",
            "안녕하세요",
        });
        builder.makeString("밤에");                // 별도의 문자열
        builder.makeItems(new String[]{           // 별도의 개별항목
            "안녕하세요",
            "안녕히 주무세요",
            "안녕히 계세요",
        });
        builder.close();                           // 문서를 완성시킨다
    }
}

 

 

(2) Builder - 생성 기능을 갖는 클래스들의 추상클래스

public abstract class Builder {
    public abstract void makeTitle(String title);
    public abstract void makeString(String str);
    public abstract void makeItems(String[] items);
    public abstract void close();
}

 

 

(3) HTMLBuilder - 생성 기능을 갖는 클래스 1

public class HTMLBuilder extends Builder {
    private String filename;                                 // 작성할 파일명
    private PrintWriter writer;                               // 파일에 쓸 PrintWriter
    public void buildTitle(String title) {                       // HTML 파일의 타이틀
        filename = title + ".html";                           // 타이틀을 기초로 파일명을 결정
        try {
            writer = new PrintWriter(new FileWriter(filename)); // PrintWriter을 만든다
        } catch (IOException e) {
            e.printStackTrace();
        }
        writer.println("<html><head><title>" + title + "</title></head><body>"); 
								// 타이틀 출력
        writer.println("<h1>" + title + "</h1>");
    }
    public void buildString(String str) {                        // HTML 파일에서의 문자열
        writer.println("<p>" + str + "</p>");                   // <p> 태그로 출력
    }
    public void buildItems(String[] items) {                     // HTML 파일에서의 개별항목
        writer.println("<ul>");                                 // <ul>과 <li>로 출력
        for (int i = 0; i < items.length; i++) {
            writer.println("<li>" + items[i] + "</li>");
        }
        writer.println("</ul>");
    }
    public void buildDone() {                                 // 문서의 완성
        writer.println("</body></html>");                     // 태그를 닫는다
        writer.close();                                        // 파일을 닫는다
    }
    public String getResult() {
        return filename;                                      // 파일명을 반환한다
    }
}

 

 

(4) TextBuilder - 생성 기능을 갖는 클래스 2

public class TextBuilder extends Builder {
    private StringBuffer buffer = new StringBuffer();           // 필드의 문서를 구축한다.
    public void makeTitle(String title) {                       // 일반 텍스트의 제목
        buffer.append("==============================\n");     // 장식선
        buffer.append("『" + title + "』\n");                   // 『』 사용한 타이틀
        buffer.append("\n");                                // 빈행
    }
    public void makeString(String str) {                       // 일반 텍스트에서의 문자열
        buffer.append('■' + str + "\n");                     // ■ 글머리 기호 붙은 문자열
        buffer.append("\n");                                // 빈 행
    }
    public void makeItems(String[] items) {                   // 일반 텍스트에서의 개별항목
        for (int i = 0; i < items.length; i++) {
            buffer.append(" ㆍ" + items[i] + "\n");            // ㆍ 글머리 기호 붙은 항목
        }
        buffer.append("\n");                               // 빈 행
    }
    public void close() {                                   // 문서의 완성
        buffer.append("==============================\n");     // 장식선
    }
    public String getResult() {                              // 완성한 문서
        return buffer.toString();                             // StringBuffer을 String으로 변환
    }
}

 

 

(5) Main

public class Main {
    public static void main(String[] args) {
        if (args.length != 1) {
            usage();
            System.exit(0);
        }
        if (args[0].equals("plain")) {
            TextBuilder textbuilder = new TextBuilder();
            Director director = new Director(textbuilder);
            director.construct();
            String result = textbuilder.getResult();
            System.out.println(result);
        } else if (args[0].equals("html")) {
            HTMLBuilder htmlbuilder = new HTMLBuilder();
            Director director = new Director(htmlbuilder);
            director.construct();
            String filename = htmlbuilder.getResult();
            System.out.println(filename + "가 작성되었습니다.");
        } else {
            usage();
            System.exit(0);
        }
    }
    public static void usage() {
        System.out.println("Usage: java Main plain 일반 텍스트로 문서작성");
        System.out.println("Usage: java Main html  HTML 파일로 문서작성");
    }
}
728x90

댓글