[Design Pattern]GoF 의 Design Pattern - Creational Patterns - Builder
Definition
복잡한 객체의 구성을 독립시켜 같은 구성을 다르게 표현 할 수 있도록 한다.
분류 |
설명 |
이름(Name) |
Builder |
의도(Insert) |
복잡한 객체를 생성하는 방법과 표현하는 방법을 정의하는 클래스를 별도로 분리하여 서로 다른 표현이라도 이를 생성할 수 있는 동일한 구축 공정을 제공할 수 있도록 한다. |
문제점(Problem) |
|
해결법(Solution) |
|
관계자(Participant)와 협력자(Collaborator) |
|
결과(Consequence) |
1. 제품에 대한 내부 표현을 다양하게 변화할 수 있다. Builder 객체는 디렉터를 제공하고 제품을 합성하기 위해 필요한 추상 인터페이스를 정의하고 있다. 빌더를 통해서 제품이 어떤 요소들로 합성되는지 각 요소들의 표현 방법이 무엇인지를 은닉할 수 있게 된다. 즉, 빌더만이 어떤 요소로 전체 제품을 합성하고 그 요소들이 어떤 타입들로 구현되는지를 알고 있을 뿐이다. 2. 생성과 표현에 필요한 코드를 분리한다. Builder 패턴을 사용하면, 복합 객체를 생성하고 복합 객체의 내부 표현을 방법을 별도의 모듈로 정의할 수 있다. 클라이언트는 제품의 내부 구조를 정의한 클래스는 전혀 모른채, 빌더와의 상호작용을 통해서 필요한 복합 객체를 생성하게 된다. 3. 복합 객체를 생성하는 공정을 좀더 세밀하게 나눌 수 있다. 한번에 복합 객체를 생성하는 것과 같이 Builder 패턴에서는 디렉터의 통제하에 하나씩 내부 합성 요소들을 만들어 나간다. 디렉터가 빌더로부터 만들어진 전체 복합 객체를 되돌려 받을 때까지 제품 합성의 과정을 계속 이루어진다. |
구현(Implementation) |
추상 클래스인 Builder 클래스에 디렉터가 요청하는 각각의 요소들을 생성하는 오퍼레이션들을 정의한다. 기본적으로 여기 정의된 오퍼레이션은 아무것도 구현되지 않은 단순한 인터페이스일 뿐이다. 이 클래스를 상속하는 서브클래스 ConcreteBuilder에서 자신에게 필요한 요소를 생성하도록 부모 클래스의 오퍼레이션을 재정의한다. 1. 조합과 구축에 필요한 인터페이스를 정의한다. 빌더는 단계별로 제품들을 구축한다. 이를 위해서 모든 종류의 제품을 생성하기에 필요한 일반화된 오페레이션들을 정의한다. 2. 제품에 대한 추상 클래스는 필요 없는가? 일반적으로 제품은 상세화된 Builder클래스의 서브클래스에 의해 생성되는데, 이는 제품마다 그 제품을 표현하는 방법이 다르고 이들 다른점에서 어떠한 공통점도 찾을 수 없기 때문에 하나의 슈퍼클래스를 정의하기 어렵다. 3. Builder에 있는 메소드에 대해서는 구현을 제공하지 않는게 일반적이다. C++로 구현할 때 빌더에 정의된 메소드를 의도적으로 가상 함수로 정의하지 않는다. |
UML class diagram
Participants
The classes and/or objects participating in this pattern are:
- Builder(VehicleBuilder)
- specifies an abstract interface for creating parts of a Product object
- ConcreteBuilder(MotorCycleBuilder, CarBuilder, ScooterBuilder)
- constructs and assembles parts of the product by implementing the Builder interface
- defines and keeps track of the representation it creates
- provides an interface for retrieving the product
- Director(Shop)
- constructs an object using the Builder interface
- Product(Vehicle)
- represents the complex object under construction. ConcreteBuilder builds the product's internal representation and defines the process by which it's assembled
- includes classes that define the constituent parts, including interfaces for assembling the parts into the final result
Sample code in C#
This structural code demonstrates the Builder pattern in which complex objects are created in a step-by-step fashion. The construction process can create different object representations and provides a high level of control over the assembly of the objects
// Builder pattern -- Structure example //-------------------------------------------------------- // Copyright (C) 2001 - 2002, Data & Object Factory // All rights reserved. www.dofactory.com // // You are free to use this source code in your // applications as long as the original copyright // notice is included. // // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT // WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF // MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. //-------------------------------------------------------- using System; using System.Collections; // "Director" class Director { // Methods public void Construct( Builder builder ) { builder.BuildPartA(); builder.BuildPartB(); } } // "Builder" abstract class Builder { // Methods abstract public void BuildPartA(); abstract public void BuildPartB(); abstract public Product GetResult(); } // "ConcreteBuilder1" class ConcreteBuilder1 : Builder { // Fields private Product product; // Methods override public void BuildPartA() { product = new Product(); product.Add( "PartA" ); } override public void BuildPartB() { product.Add( "PartB" ); } override public Product GetResult() { return product; } } // "ConcreteBuilder2" class ConcreteBuilder2 : Builder { // Fields private Product product; // Methods override public void BuildPartA() { product = new Product(); product.Add( "PartX" ); } override public void BuildPartB() { product.Add( "PartY" ); } override public Product GetResult() { return product; } } // "Product" class Product { // Fields ArrayList parts = new ArrayList(); // Methods public void Add( string part ) { parts.Add( part ); } public void Show() { Console.WriteLine( "\nProduct Parts -------" ); foreach( string part in parts ) Console.WriteLine( part ); } } /// <summary> /// Client test /// </summary> public class Client { public static void { // Create director and builders Director director = new Director( ); Builder b1 = new ConcreteBuilder1(); Builder b2 = new ConcreteBuilder2(); // Construct two products director.Construct( b1 ); Product p1 = b1.GetResult(); p1.Show(); director.Construct( b2 ); Product p2 = b2.GetResult(); p2.Show(); } } Output Product Parts ------- |
This real-world code demonstates the Builder pattern in which different vehicles are assembled in a step-by-step fashion. The Shop uses VehicleBuilders to construct a variety of Vehicles in a series of sequential steps.
// Builder pattern -- Real World example //-------------------------------------------------------- // Copyright (C) 2001 - 2002, Data & Object Factory // All rights reserved. www.dofactory.com // // You are free to use this source code in your // applications as long as the original copyright // notice is included. // // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT // WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF // MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. //-------------------------------------------------------- using System; using System.Collections; // "Director" class Shop { // Methods public void Construct( VehicleBuilder vehicleBuilder ) { vehicleBuilder.BuildFrame(); vehicleBuilder.BuildEngine(); vehicleBuilder.BuildWheels(); vehicleBuilder.BuildDoors(); } } // "Builder" abstract class VehicleBuilder { // Fields protected Vehicle vehicle; // Properties public Vehicle Vehicle { get{ return vehicle; } } // Methods abstract public void BuildFrame(); abstract public void BuildEngine(); abstract public void BuildWheels(); abstract public void BuildDoors(); } // "ConcreteBuilder1" class MotorCycleBuilder : VehicleBuilder { // Methods override public void BuildFrame() { vehicle = new Vehicle( "MotorCycle" ); vehicle[ "frame" ] = "MotorCycle Frame"; } override public void BuildEngine() { vehicle[ "engine" ] = "500 cc"; } override public void BuildWheels() { vehicle[ "wheels" ] = "2"; } override public void BuildDoors() { vehicle[ "doors" ] = "0"; } } // "ConcreteBuilder2" class CarBuilder : VehicleBuilder { // Methods override public void BuildFrame() { vehicle = new Vehicle( "Car" ); vehicle[ "frame" ] = "Car Frame"; } override public void BuildEngine() { vehicle[ "engine" ] = "2500 cc"; } override public void BuildWheels() { vehicle[ "wheels" ] = "4"; } override public void BuildDoors() { vehicle[ "doors" ] = "4"; } } // "ConcreteBuilder3" class ScooterBuilder : VehicleBuilder { // Methods override public void BuildFrame() { vehicle = new Vehicle( "Scooter" ); vehicle[ "frame" ] = "Scooter Frame"; } override public void BuildEngine() { vehicle[ "engine" ] = "none"; } override public void BuildWheels() { vehicle[ "wheels" ] = "2"; } override public void BuildDoors() { vehicle[ "doors" ] = "0"; } } // "Product" class Vehicle { // Fields private string type; private Hashtable parts = new Hashtable(); // Constructors public Vehicle( string type ) { this.type = type; } // Indexers public object this[ string key ] { get{ return parts[ key ]; } set{ parts[ key ] = value; } } // Methods public void Show() { Console.WriteLine( "\n---------------------------"); Console.WriteLine( "Vehicle Type: {0}", type ); Console.WriteLine( " Frame : {0}", parts[ "frame" ] ); Console.WriteLine( " Engine : {0}", parts[ "engine" ] ); Console.WriteLine( " #Wheels: {0}", parts[ "wheels" ] ); Console.WriteLine( " #Doors : {0}", parts[ "doors" ] ); } } /// <summary> /// BuilderApp test /// </summary> public class BuilderApp { public static void { // Create shop with vehicle builders Shop shop = new Shop(); VehicleBuilder b1 = new ScooterBuilder(); VehicleBuilder b2 = new CarBuilder(); VehicleBuilder b3 = new MotorCycleBuilder(); // Construct and display vehicles shop.Construct( b1 ); b1.Vehicle.Show(); shop.Construct( b2 ); b2.Vehicle.Show(); shop.Construct( b3 ); b3.Vehicle.Show(); } } Output Vehicle Type: Scooter |