본문 바로가기
프로그래밍/JAVA

디자인 패턴 Builder Pattern

by 애플 로그 2021. 2. 24.
반응형

디자인 패턴  Builder Pattern

 

개념이 어렵기는 하는데,  전체를 구성하고 있는 각 부분을 만들고 단계를 밟아 만들어 나가는 패턴을 Builder Pattern이라고 해요. Builder Pattern 다이어그램은 다음과 같아요.

 

 

 

예제를 보도록 하자.

예제는 Builder Pattern을 사용해서 '일반 텍스트 문서'와 'HTML 형태의 문서'를 만드는 프로그램이다.
Builder 클래스에서는 문서를 구성하기 위한 메소드를 결정하고, Director 클래스는 그 메소드를 사용해서 구체적인 하나의 문서를 만든다. Builder 클래스는 추상 클래스로서 실제의 처리는 기술되어 있지 않고, 추상 메소드만 선언되어 있다. 문서 작성을 위한 구체적인 처리를 결정하는 것은 Builder 클래스의 하위 클래스인 TextBuilder, HTMLBuilder클래스이다.

 

 

- Builder.java

  1 package Builder_pattern; 
  2 
  3 public abstract class Builder { 
  4     public abstract void makeTitle(String title); 
  5     public abstract void makeString(String str); 
  6     public abstract void makeItems(String[] items); 
  7     public abstract void close(); 
  8 }

- Director.java

  1 package Builder_pattern; 
  2 
  3 public class Director { 
  4     private Builder builder; 
  5      
  6     public Director(Builder builder){ 
  7         this.builder = builder; 
  8     } 
  9      
 10     public void construct(){ 
 11         builder.makeTitle("Greeting"); 
 12         builder.makeString("아침과 낮에"); 
 13         builder.makeItems(new String[]{ 
 14                 "좋은 아침입니다."
 15                 "안녕하세요"
 16         }); 
 17         builder.makeString("밤에"); 
 18         builder.makeItems(new String[]{ 
 19                 "안녕하세요"
 20                 "안녕히 주무세요."
 21                 "안녕히 계세요."
 22         }); 
 23         builder.close(); 
 24     } 
 25 }

 

Director 클래스에서는 Builder 클래스로 선언되어 있는 메소드를 사용해서 문서를 만든다. Director 클래스의 생성자의 인수는 Builder형이다. 그러나 실제로는 Builder 클래스의 인스턴스가 인수로 주어지는 경우는 없다. 왜냐하면 Builder클래스는 추상 클래스이므로 인스턴스를 만들 수 없기 때문이다. Director의 생성자에게 실제로 전달되는 것은 Builder 클래스의 하위 클래스인 TextBuilder, HTMLBuilder의 인스턴스이다.

Construct 메소드는 문서를 만드는 메소드이며, Builder에서 선언되어 있는 메소드만을 사용한다. 이 메소드가 호출되면 각 구성물들이 조립되어 하나의 완성품이 나오게 된다.


- TextBuilder.java

  1 package Builder_pattern; 
  2 
  3 public class TextBuilder extends Builder{ 
  4     private StringBuffer buffer = new StringBuffer(); 
  5      
  6     @Override 
  7     public void makeTitle(String title) { 
  8         // TODO Auto-generated method stub 
  9         buffer.append("====================\n"); 
 10         buffer.append("[" + title + "]\n"); 
 11         buffer.append("\n"); 
 12     } 
 13 
 14     @Override 
 15     public void makeString(String str) { 
 16         // TODO Auto-generated method stub 
 17         buffer.append('■' + str + "\n"); 
 18         buffer.append("\n"); 
 19     } 
 20 
 21     @Override 
 22     public void makeItems(String[] items) { 
 23         // TODO Auto-generated method stub 
 24         for(String item : items){ 
 25             buffer.append(" ▶" + item + "\n"); 
 26         } 
 27         buffer.append("\n"); 
 28          
 29     } 
 30 
 31     @Override 
 32     public void close() { 
 33         // TODO Auto-generated method stub 
 34         buffer.append("====================\n"); 
 35     } 
 36      
 37     public String getResult(){ 
 38         return buffer.toString(); 
 39     } 
 40 
 41 }

- HTMLBuilder.java

  1 package Builder_pattern; 
  2 
  3 import java.io.FileWriter; 
  4 import java.io.IOException; 
  5 import java.io.PrintWriter; 
  6 
  7 public class HTMLBuilder extends Builder{ 
  8     private String filename; 
  9     private PrintWriter writer; 
 10      
 11     @Override 
 12     public void makeTitle(String title) { 
 13         // TODO Auto-generated method stub 
 14         filename = title + ".html"
 15         try
 16             writer = new PrintWriter(new FileWriter(filename)); 
 17         }catch(IOException e){ 
 18             e.printStackTrace(); 
 19         } 
 20         writer.println("<html><head><title>" + title + "</title></head><body>"); 
 21         writer.println("<h1>" + title + "</h1>"); 
 22     } 
 23 
 24     @Override 
 25     public void makeString(String str) { 
 26         // TODO Auto-generated method stub 
 27         writer.println("<p>" + str + "</p>"); 
 28     } 
 29 
 30     @Override 
 31     public void makeItems(String[] items) { 
 32         // TODO Auto-generated method stub 
 33         writer.println("<ul>"); 
 34         for(String item : items){ 
 35             writer.println("<li>" + item + "</li>"); 
 36         } 
 37         writer.println("</ul>"); 
 38     } 
 39 
 40     @Override 
 41     public void close() { 
 42         // TODO Auto-generated method stub 
 43         writer.println("</body></html>"); 
 44         writer.close(); 
 45     } 
 46      
 47     public String getResult(){ 
 48         return filename; 
 49     } 
 50 } 

- Main.java

  1 package Builder_pattern; 
  2 
  3 public class Main { 
  4     public static void main(String[] args){ 
  5         if(args.length != 1){ 
  6             usage(); 
  7             System.exit(0); 
  8         } 
  9          
 10         if(args[0].equals("plain")){ 
 11             TextBuilder tb = new TextBuilder(); 
 12             Director director = new Director(tb); 
 13             director.construct(); 
 14             String result = tb.getResult(); 
 15             System.out.println(result); 
 16         }else if(args[0].equals("html")){ 
 17             HTMLBuilder hb = new HTMLBuilder(); 
 18             Director director = new Director(hb); 
 19             director.construct(); 
 20             String filename = hb.getResult(); 
 21             System.out.println(filename + "가 작성되었습니다."); 
 22         }else
 23             usage(); 
 24             System.exit(0); 
 25         } 
 26     } 
 27 
 28     private static void usage() { 
 29         // TODO Auto-generated method stub 
 30         System.out.println("Usage : java Main plain => 일반 텍스트로 문서작성"); 
 31         System.out.println("Usage : java Main html => HTML 파일로 문서작성"); 
 32     } 
 33 }

 

Main 클래스에서는 command args에 따라 일반 텍스트 또는 HTML 파일 문서로 결과값을 보여줄 것이다.

TextBuilder와 HTMLBuilder는 Builder의 하위 클래스이고 Director는 Builder의 메소드만을 사용해서 문서를 작성한다. Builder의 메소드만을 사용한다는 것은 'Director는 실제로 동작하는 것이 TextBuilder인지, HTMLBuilder인지 모른다'는 의미이다. 따라서 Builder는 문서를 구축하려는 목적을 달성하기 위해 필요 충분한 메소드군을 선언할 필요가 있다.

 

결과

 

 

[HTML 문서]

참고 1.
Builder 클래스는 문서를 구축할 때 필요 충분한 메소드군을 선언해야 한다. Director클래스에 주어진 도구는 Builder 클래스가 제공하는 도구이기 때문에 Builder 클래스의 메소드로서 무엇을 준비해야 할지는 중요하다. 더구나 Builder 클래스는 앞으로 늘어날지도 모르는 Builder 클래스의 하위 클래스의 요구에도 대응할 필요가 있다.

참고 2.
Main 클래스는 Builder 클래스의 메소드를 모른다.(호출하지 않는다.) Main 클래스는 Director 클래스의 construct 메소드만을 호출한다. 그러면 Director 클래스 안에서 알아서 처리해서 결과값을 만들어 낸다. 한편 Director 클래스가 알고 있는 것은 Builder 클래스이다. Director 클래스는 Builder 클래스의 메소드를 사용해서 문서를 구축한다. 그러나 Director 클래스는 자신이 실제로 이용하고 있는 클래스가 사실은 무엇인지 모른다. TextBuilder인지, HTMLBuilder인지 또는 Builder의 다른 하위 클래스인지 모른다. Director 클래스는 Builder 클래스의 메소드만을 사용하고 있고, Builder 클래스의 하위 클래스는 그 메소드를 구현하기 때문이다.

Director 클래스가 자신이 이용하고 있는 Builder 클래스의 하위 클래스를 모르는 것은 정말 잘 된 일이다. 왜냐하면 모르기 때문에 교체할 수 있기 때문이다.

 

 

[출처] "Java 언어로 배우는 디자인 패턴 입문"

댓글