블로그 이미지
Kanais
Researcher & Developer 퍼즐을 완성하려면 퍼즐 조각들을 하나 둘씩 맞춰나가야 한다. 인생의 퍼즐 조각들을 하나 둘씩 맞춰나가다 보면 인생이란 퍼즐도 완성되는 날이 오려나...?

calendar

1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

Notice

2015. 4. 16. 10:10 Programming/Design Pattern



참고 서적 : GOF의 디자인패턴 – Addison Wesley – 에릭감마, 리처드 헬름, 랄프 존슨, 존 블리시디스 지음. 김정아 옮김.


 BuilderTest.zip


Builder

복합 객체의 생성 과정과 표현 방법을 분리하여 동일한 생성 절차에서 서로 다른 표현 결과를 만들 수 있게 하는 패턴입니다.

 

Builder패턴의 의도

복잡한 개체를 생성하는 방법과 표현하는 방법을 정의하는 클래스를 별도로 분리하여, 서로 다른 표현이라도 이를 생성할 수 있는 동일한 절차를 제공할 수 있도록 합니다.

 

활용성

빌더 패턴은 다음의 경우에 사용합니다.

-      복합 개체의 생성 알고리즘이 이를 합성하는 요소 객체들이 무엇인지 이들의 조립 방법에 독립적일 때

-      합성할 개체들의 표현이 서로 다르더라도 생성 절차에서 이를 지원해야 할 때

 

구조

 

 

 

Builder : Product개체의 일부 요소들을 생성하기 위한 추상 인터페이스를 정의합니다.

ConcreteBuilder : Builder클래스에 정의된 인터페이스를 구현하며, 제품의 부품들을 모아 빌더를 복합합니다.

Director : Builder 인터페이스를 사용하는 개체를 합성합니다.

Product : 생성할 복합개체를 표현합니다. ConcreteBuilder는 제품(Product)의 내부 표현을 구축하고 복합 개체가 어떻게 구성되는지에 관한 절차를 정의합니다.

 

결과

빌더 패턴의 장단점은 다음과 같습니다.

 

장점

—  제품에 대한 내부 표현의 다양화

Builder클래스는 Director클래스에게 개체를 생성할 수 있는 인터페이스를 제공하고 생성 되는 개체의 내부구조나 표현방식 등은 builder클래스 내부로 숨기는 형태입니다. 개체를 복합할 때는 builder에 정의된 추상 인터페이스를 통해 사용자가 동작하기 때문에 새로운 제품의 표현 방법이나 제품의 복합 방법이 바뀔 때 builder 클래스의 상속을 통해 새로운 서브클래스를 정의하면 됩니다.

 

—  생성과 표현에 필요한 코드 분리

생성과 표현에 필요한 코드를 분리시켜 줌으로써 서로 간의 독립성을 줍니다. 이를 통해 Builder와 Director클래스는 서로 독립적으로 수정되거나 재 사용될 수 있습니다.

 

—  복합 개체를 생성하는 절차의 세밀화

복합 개체를 생성하는 절차를 좀더 세밀하게 나눌 수 있습니다. Builder패턴은 개체를 한꺼번에 생성하는 것이 아니라,부분 부분을 생성한 후 최종 결과를 얻어가는 방식이므로, 개체 생성 과정을 좀더 세밀히 제어할 수 있습니다.

 

단점

—  새로운 종류의 개체생성을 추가하기는 쉬우나, 개체를 구성하는 각 부분을 추가하기는 어려움

 

Builder패턴은 새로운 종류의 개체생성을 추가하기는 쉬우나, 개체를 구성하는 각 부분을 추가하기는 어렵습니다. Builder패턴에 새로운 인터페이스를 추가하면 Director클래스와 Builder클래스의 상속하는 concreteBuilder클래스를 모두 클래스를 수정해야 하는 문제가 생깁니다.

따라서 Builder패턴을 적용하고자 할 경우에는 생성되는 개체를 구성하는 부분들을 명확히 해서 수정 할 부분이 없게 하는 것이 중요합니다.

 

예제 소스

 

Class Diagram

 

소스 설명

class Element

    {

        public string Name

        {

            get;

            private set;

        }

        public string WallName

        {

            get;

            private set;

        }

        public int Wall

        {

            get;

            private set;

        }

        public string FloorName

        {

            get;

            private set;

        }

        public int Floor

        {

            get;

            private set;

        }

        ArrayList others = new ArrayList();

        public Element(string name)

        {

            Name = name;

            Console.WriteLine("{0}집을 짓기 시작합니다", Name);

            Thread.Sleep(1000);

        }

        public void SetWall(string name, int num)

        {

            WallName = name;

            Wall = num;

            Console.WriteLine("{0}개의 재료를 소모하여 {1}벽을 세우고 있습니다.", Wall, WallName);

            Thread.Sleep(1000);

        }

        public void SetFloor(string name, int num)

        {

            FloorName = name;

            Floor = num;

            Console.WriteLine("{0}개의 재료를 소모하여 {1}바닥을 깔고 있습니다.", FloorName, Floor);

        }

        public void SetOthers(object other)

        {

            others.Add(other);

            Console.WriteLine("{0} 재료도 사용합니다.",other);

            Thread.Sleep(500);

        }

        public override string ToString()

        {

            string st = string.Format("{0}\n{1}벽 : {2}개\t{3}바닥 : {4}", Name, WallName, Wall, FloorName, Floor);

           

            foreach (string str in others)

            {

                st += "\n" + str;

            }

            return st;

        }

Product(Element Class)에서는 생성할 복합 개체(건물)을 표현합니다. 슬립을 넣어서 건물이 만들어 지는 과정을 보여주면서 Builder 패턴을 느낄 수 있게 하였습니다.

 

interface StructureBuilder

    {

        Element CreateStructure();

    }

Builder(StructureBuilder Interface) 에서는 Product(건물) 개체의 일부 요소들을 생성하기 위한 인터페이스를 정의합니다.

 

class BuildingBuilder:StructureBuilder

    {

        #region StructureBuilder 멤버

        public Element CreateStructure()

        {

            Element element = new Element("빌딩");

            element.SetWall("시멘트"500);

            element.SetFloor("대리석"600);

            element.SetOthers("철근");

            element.SetOthers("벽돌");

            return element;

        }

        #endregion

    }

 

class HouseBuilder:StructureBuilder

    {

        #region StructureBuilder 멤버

        public Element CreateStructure()

        {

            Element element = new Element("집");

            element.SetWall("황토"100);

            element.SetFloor("온돌"50);

            element.SetOthers("기와");

            return element;

        }

        #endregion

    }

}

ConcreteBuilder(BuildingBuilder, HouseBuilder) 에서는 Builder(StructureBuilder)에 정의된 인터페이스를 구현하며, 건물의 재료들을 모아 빌더를 복합합니다.

 

class Architect

    {

        List<StructureBuilder> architect = new List<StructureBuilder>();

        public enum StructureType

        {

            BuildingType,

            HouseType

        }

        public Architect()

        {

            architect.Add(new BuildingBuilder());

            architect.Add(new HouseBuilder());

        }

 

        public Element Build(StructureType rt)

        {

            return architect[(int)rt].CreateStructure();

        }

    }

}

Director(Architect Class) 에서는 Builder 인터페이스를 사용하는 개체를 합성합니다. 소스를 보면 건축가가 Build 메서드로 오더받으면 빌딩, 집의 건설방법을 사용하여 해당 건물을 건축해서 반환하는 것을 알 수 있습니다.

 

class Program

    {

        static void Main(string[] args)

        {

            Architect architect = new Architect();

            Element element = architect.Build(Architect.StructureType.BuildingType);

            Console.WriteLine(element);

            element = architect.Build(Architect.StructureType.HouseType);

            Console.WriteLine(element);

        }

    }

Architect(건축가) 개체를 생성하여 개체안의 Build 메서드에 오더 할 건물의 타입을 넘겨주면 건축가는 건물을 건설해 줍니다.

 

결과 화면

 

'Programming > Design Pattern' 카테고리의 다른 글

[Design Pattern] Template Method  (0) 2015.04.16
[Design Pattern] Bridge Pattern  (0) 2015.04.16
[Design Pattern] Abstract Factory  (0) 2015.04.16
posted by Kanais