[Design Pattern]Builder
1. 개요
뭔가가 만들어 지는 과정은 꽤나 복잡할 수가 있습니다. 게다가 그 복잡한 과정이 순서대로 실행되어야 할 때도 있습니다. 객체의 생성에 있어서 이런 복잡한 과정들을 분리해 내는 것이 Builder 패턴입니다.
2. 예제
//---------------- 복잡한 과정을 거쳐서 만들어 지는 객체가 될 Hero 클래스 ---------------- package design.pattern.builder; public class Hero { private String armSource; private String legSource; private String name; public Hero(String name) { super(); this.name = name; } public void setArmSource(String armSource) { this.armSource = armSource; } public void setLegSource(String legSource) { this.legSource = legSource; } public void showResult(){ System.out.println(armSource +"로 만든 팔과 " + legSource +"로 만든 다리를 가진 " + name); } }
//---------------- 복잡한 Hero 객체를 만들어내기 위한 객체 생성과정을 관리하는 Builder 인터페이스 ---------------- package design.pattern.builder; public interface Builder { void makeArm(); void makeLeg(); Hero getResult(); }
//---------------- 복잡한 Hero 객체를 실제로 만들어내는 Builder의 구현체인 배트맨 찍어내는 클래스 ------------------ package design.pattern.builder; public class BatmanBuilder implements Builder { private Hero batman; BatmanBuilder(){ batman = new Hero("배트맨"); } public void makeArm() { batman.setArmSource("돈지랄"); } public void makeLeg() { batman.setLegSource("돈지랄"); } public Hero getResult() { return batman; } }
//---------------- Builder를 관리해 주는 Director ---------------- package design.pattern.builder; public class Director { private Builder builder; public Director(Builder builder) { this.builder = builder; } public void build(){ builder.makeArm(); builder.makeLeg(); } public Hero getHero(){ return builder.getResult(); } }
//---------------- Director를 이용해 Hero를 찍어내는 Test클래스 ------------- package design.pattern.builder; public class Test { public static void main(String[] args) { Builder builder = new BatmanBuilder(); Director director = new Director(builder); director.build(); Hero hero = director.getHero(); hero.showResult(); } } ---------------- 테스트 결과 ------------- 돈지랄로 만든 팔과 돈지랄로 만든 다리를 가진 배트맨
Hero라는 클래스가 있습니다. 이 클래스는 그냥 생성자만 호출해서는 아무 쓸모없는 클래스입니다. 이런 저런 정보들이 많이 쎄팅이 되어야 비로소 쓸만한 객체가 됩니다.(예제에서는 setArmSource()과 setLegSource()와 같은 게 그런 복잡한 세팅 과정에 관여하는 메쏘듭니다.) 따라서 이 클래스의 객체를 생성하는 과정은 매우 번거롭습니다.
이런 번거로운 과정을 Director에서 간단하게 build()라는 메쏘드로 해결을 하려고 합니다. build()라는 메쏘드는 참 간단한 것 같은데, 번거로운 과정을 어떻게 다 커버하느냐는 결국 Builder에 위임해서 해결합니다.
Builder는 비교적 세부적인 사항들을 다룹니다. 이에 비해 Director는 좀 더 포괄적인 과정은 다룹니다. 위의 예제의 경우는 Builder는 팔은 어떻게 만들어 지고 다리는 어떻게 만들어지는 지 등과 같은 것을 다루며(세부적인 사항인 makeArm(), makeLeg()와 같은 메쏘드), Director는 팔을 만들고 다리를 만들면 대략 Hero 하나 완성시킬 수 있다는 전체적인 로직(포괄적인 과정인 build() 메쏘드)을 다룹니다. 즉, Director는 다른 Hero를 만드는데도 활용할 수 있지만, Builder는 각각의 Hero에 국한됩니다.
위의 예제는 예제인 만큼 간단하게 만들었습니다만, Hero를 만들기 위해서 수십수백 가지의 정보가 세팅되어야 한다고 칩시다. 이럴 때, Hero의 생성자에 그런 정보들을 다 세팅해줄 수는 없습니다.
3. UML을 벗어나서...
위에서는 등장인물이 Builder(interface)와 그 구현체들, 그를 관리하는 Director 그리고 만들어지는 생산품(Hero) 등이 있었습니다. 그러나, 이는 그냥 전형적이 UML 모냥새를 나타내는 것 뿐이고, Builder 패턴에 있어서는 저런 UML을 벗어나는 경우들이 허다합니다.
Builder에서의 포인트는 "뭔가 복잡한 과정을 거쳐 만들어지는 객체가 있는데, 이때 이 복잡한 과정을 Builder에게 담당시키겠다"는 것입니다. 따라서 Builder와 Product 두 개만으로도 구성될 수 있습니다. 즉, Builder 자체가 Abstract Class나 인터페이스가 아니라 그냥 클래스 일수도 있습니다.
StringBuilder와 같은 것이 대표적인 예입니다. StringBuilder는 이름 그대로 String을 만들어냅니다. 코드를 봅시다.
String ab = new StringBuilder("a").append("b").toString();
여기서 StringBuilder는 결국 "ab"라는 String을 만들기 위한 것입니다. StringBuilder 자체가 의미를 가지는 것이 아니라, 만들어 내는 String이 의미를 가지는 것입니다.
'개발 > JAVA' 카테고리의 다른 글
오라클, 자바 SE 전면 유료화…서브스크립션 모델 전환 (0) | 2018.08.13 |
---|---|
[Design Pattern]Mediator (0) | 2018.07.17 |
[Design Pattern]Flyweight (0) | 2018.07.16 |
[Design Pattern]Prototype (0) | 2018.07.16 |
[Design Pattern]Observer (0) | 2018.07.16 |