아래의 글은 언제나 휴일 출판사의 장문석님의 "Escort GoF의 디자인 패턴" 도서의 내용을 정리한 것 입니다. (http://cafe.daum.net/ehclub.net/S8l6/11)

 

원형 패턴(Prototype Pattern)

 

1.1 개요

 

원형 패턴은 미리 만들어진 개체를 복사하여 개체를 생성하는 패턴을 말합니다. 그리고, 이 때 미리 만들어진 개체를 원형 개체라 부릅니다. 일반화 관계로 표현을 할 때 파생클래스의 개수가 과도히 많아지고 각 클래스의 메서드에서 수행하는 알고리즘에 차이가 없고 생성 시에 개체의 속성에 차이만 있다면 원형 패턴을 사용하는 것이 효과적입니다.

 

1.2 시나리오

 

다음 주에는 거제도와 통영으로 2박 3일 여행을 가기로 하였습니다. 그 곳의 해안 지역은 리아시스식 해안 형태를 지니고 있어 줌 렌즈를 갖고 가는 것이 좋을 것 같다는 생각을 하고 있습니다. 이번 기회에 괜찮은 줌 렌즈를 하나 구입을 하기 위해 EHLand 쇼핑몰을 검색을 해 보았습니다.

 

EHLand 쇼핑몰에는 다양한 형태의 줌 렌즈들이 있는데 이들 중에 무엇을 사는 것이 좋을지 생각하다보니 어떠한 원리로 만들어져 있는지 궁금해 졌습니다. EHLand의 예릭플 씨한테 물어보면 궁금증이 풀릴 것 같아 이메일을 보냈습니다.

 

 

안녕하세요, 예릭플 씨.

지난 번에 EHLand 사의 렌즈 개발 과정에 대해 친절히 소개해 하셔서 감사드립니다. 이번에 남해안에 여행을 가게 되어 줌 렌즈를 하나 구입을 하려고 합니다. '어떤 렌즈를 구입을 할까?' 고민을 하다보니 각 렌즈들이 만들어지는 과정이 궁금해졌습니다.

 

이메일을 보내고 난 다음 날 바로 예릭플 씨의 답변 메일을 받게 되었고 궁금증이 풀리게 되었습니다.

 

 

혁재 아버지, 안녕하세요.

가족끼리 남해에 여행간다고 하니 부럽네요. 혁재가 많이 좋아할 거 같군요.

이번에는 줌 렌즈를 만드는 공정이 궁금하신가 보네요. 줌 렌즈를 만드는 생산 라인은 복사기와 비슷한 원리로 만들어집니다. EHLand의 모든 줌 렌즈는 모두 같은 구조로 되어 있고 들어가는 모듈도 크게 다르지 않습니다. 각 생산 라인마다 견본 줌 렌즈가 있는데 이들은 기본 구조는 동일하게 제작되어 있습니다. 물론, 각 견본 줌 렌즈들은 서로 거리 조절링에 설정되어 있는 최소 거리와 최대 거리나 조리개 조절링에 설정된 최소치와 최대치가 다릅니다. 생산 라인의 기계는 견본 줌 렌즈의 이들 속성을 확인하여 동일하게 설정된 렌즈를 생산하고 있지요.

 

1.3 디자인

 

여기에서는 줌 렌즈와 줌 렌즈 생산 라인 두 개의 형식으로 구성된 예를 들고자 합니다. 줌 렌즈는 자신을 복제할 수 있는 메소드를 제공하고 있어야 합니다. 클래스 이름은 ZoomLens라 정합시다. 줌 렌즈 생산 라인은 견본 줌 렌즈를 하나 갖고 있게 할 것입니다. 그리고, 제품 생산요청이 들어오면 견본을 복제한 줌 렌즈를 반환하면 될 것입니다. 줌 렌즈 생산 라인에 대한 클래스 이름은 ProLine이라 하겠습니다.

 

이번에는 정상적으로 작성되었는지를 확인하기 위한 클래스나 코드에 대해서는 논하지 않겠습니다. 여러분이 창의적으로 생각을 하셔서 작성해 보세요.

 

[그림 1] 원형 패턴 설계 예

 

1. 4 구현

 

이제 원형 패턴에 대한 예제 프로그램을 구현해 봅시다. 구현 순서는 줌 렌즈, 줌 렌즈 생산 라인 순으로 구현 하겠습니다.

 

2.4.1 줌 렌즈

 

여기에서는 다양한 줌 렌즈를 일반화 관계로 사용하지 않고 하나의 ZoomLens 클래스에서 속성만 다르게 주어 이를 기반으로 개체를 복사하여 사용하기로 하였습니다. 이에 줌 렌즈의 생성자 메서드에서는 최소 줌 레벨과 최대 줌 레벨, 최소 초점 거리, 최대 초점 거리를 입력 인자로 전달받아 생성하도록 하겠습니다. 그리고, 복제를 하기 위한 메서드가 필요할 것입니다. 자신을 복제한 개체를 반환하는 메서드 이름은 Clone이라고 정하겠습니다. 이 외에 줌 인, 줌 아웃, 초점을 가까운 곳으로 이동, 먼 곳으로 이동시키는 기능 및 피사체를 사진을로 변환하는 기능을 추가하도록 하겠습니다.

 

 

namespace AboutPrototypePattern
{
    class ZoomLens
    {
        public enum TypeZoomLens
        {
            NM_NM,
            NM_NF,
            NF_NF,
            MF_NF,
            MF_MF
        }

        readonly int minZoomLevel;
        readonly int maxZoomLevel;
        readonly int minFocus;
        readonly int maxFocus;
        int zoomLevel;
        int focus;

        public ZoomLens(int _minZoomLevel, int _maxZoomLevel, int _minFocus, int _maxFocus)
        {
            this.minZoomLevel = _minZoomLevel;
            this.maxZoomLevel = _maxZoomLevel;
            this.minFocus = _minFocus;
            this.maxFocus = _maxFocus;
        }

        public void Take()
        {
            Console.WriteLine("zoomLevel : {0}, focus : {1}", zoomLevel, focus);
        }

        public int ZoomIn()
        {
            if (zoomLevel < maxZoomLevel)
            {
                zoomLevel++;
            }
            return zoomLevel;
        }

        public int ZoomOut()
        {
            if (zoomLevel < minZoomLevel)
            {
                zoomLevel--;
            }
            return zoomLevel;
        }

        public int NearFocus()
        {
            if (focus > minFocus)
            {
                focus--;
            }
            return focus;
        }

        public int FacFocus()
        {
            if (focus > maxFocus)
            {
                focus++;
            }
            return focus;
        }

        public ZoomLens Clone()
        {
            return new ZoomLens(this.minZoomLevel, this.maxZoomLevel, this.minFocus, this.maxFocus);
        }
    }

 

 

 

2.4.2 줌 렌즈 생산 라인

 

생산 라인은 하나의 줌 렌즈를 견본으로 갖고 있고 이를 기반으로 복사된 렌즈를 생산하기로 하였습니다. 이를 위해 생산 라인의 생성자는 어떠한 견본 렌즈를 갖고 있을 것인지를 입력 인자로 전달받기로 하겠습니다. 그리고, 생산 요청을 받아 견본 렌즈와 동일한 속성 값을 갖는 복제된 제품을 반환하는 메서드를 만들기로 합시다. 메서드 이름은 MakeLens라 하겠습니다.

namespace AboutPrototypePattern
{
    class ProLine
    {
        ZoomLens prototype;
        

        public ProLine(AboutPrototypePattern.ZoomLens.TypeZoomLens typeZoomLens)
        {
            switch (typeZoomLens)
            {
                case ZoomLens.TypeZoomLens.NM_NM: prototype = new ZoomLens(20, 70, 1, 100); break;
                case ZoomLens.TypeZoomLens.NM_NF: prototype = new ZoomLens(20, 70, 1, 200); break;
                case ZoomLens.TypeZoomLens.NF_NF: prototype = new ZoomLens(20, 300, 1, 200); break;
                case ZoomLens.TypeZoomLens.MF_NF: prototype = new ZoomLens(70, 300, 1, 200); break;
                case ZoomLens.TypeZoomLens.MF_MF: prototype = new ZoomLens(70, 300, 10, 200); break;
            }
        }

        public ZoomLens MakeLens()
        {
            ZoomLens product = prototype.Clone();
            return product;
        }
    }
}


 

+ Recent posts