25.4 구현
반복자 패턴의 예제 프로그램을 구현하는 순서는 Element 군, Visitor 군, MyTour와 데모 코드 순으로 하겠습니다.
25.4.1 Element 군
MyTour는 사진과 일기를 통합 관리하는 컬렉션 입니다. 사진과 일기와 같이 MyTour에서 관리 가능한 요소에 대한 기반 클래스를 Element라 정하고 사진을 Picture, 일기를 Diary라 정하겠습니다.
방문자 패턴에서는 요소에 따라 다르게 처리해야 할 기능들을 구체화 된 방문자 형식을 정의를 하고 실제 요소 형식에서는 단순히 방문자를 수용하는 메서드만 정의를 합니다. 즉, 실질적인 구현은 각 요소 형식들에서 하는 것이 아니고 구체화 된 방문자에서 하는 것이죠. 단순히 요소 개체들은 수용한 방문자에 정의된 자신처리할 메서드를 호출하면 수용한 방문자에서 구체적 처리를 할 것입니다.
이를 위해 Element에서는 방문자를 수용하는 메서드를 약속합니다.
▶ Element.cs
namespace Visitor { abstract class Element { public string Name { get; private set; } public Element(string name) { Name = name; } public abstract void Accept(IVisit visitor); } }
그리고 사진과 일기에서는 수용한 방문자에 메서드 중에서 자신을 처리할 수 있는 메서드를 호출하게 재정의합시다.
▶ Picture.cs
using System; namespace Visitor { class Picture:Element { int tone; int brightness; int saturation; public Picture(string name,int tone,int brightness,int saturation):base(name) { SetInfo(tone,brightness,saturation); } public void ViewInfo() { Console.WriteLine("색조:{0} 명도:{1} 채도:{2}",tone,brightness,saturation); } public void SetInfo(int tone,int brightness,int saturation) { this.tone = tone; this.brightness = brightness; this.saturation = saturation; } public override void Accept(IVisit visitor) { visitor.VisitPicture(this); } } }
▶ Diary.cs
using System; namespace Visitor { class Diary:Element { string content; public Diary(string name,string content):base(name) { SetContent(content); } public void ViewContent() { Console.WriteLine(content); } public void SetContent(string content) { this.content = content; } public override void Accept(IVisit visitor) { visitor.VisitDiary(this); } }
25.4.2 Visitor 군
Vistor 군에서는 요소 형식에 따라 요소 개체를 처리하는 기능을 담당하는 형식들입니다. IVisit 인터페이스에서는 요소 형식인 Picture 와 Diary 개체를 처리하기 위한 메서드에 대한 약속해야 겠지요.
그리고, 방문자 패턴에 대한 응용에서는 요소 형식에 따라 처리를 다르게 할 기능으로 개체의 정보 보기와 초기화 시키기를 구현할 것입니다. 이들은 인터페이스 IVisit에서 약속한 메서드를 구체적으로 구현해야 할 것입니다.
▶ Visitor.cs
namespace Visitor { interface IVisit { void VisitPicture(Picture picture); void VisitDiary(Diary diary); } }
▶ Viewer.cs
using System; namespace Visitor { class Viewer:IVisit { public void VisitPicture(Picture picture) { Console.WriteLine("사진 제목:{0}", picture.Name); picture.ViewInfo(); } public void VisitDiary(Diary diary) { Console.WriteLine(diary.Name); diary.ViewContent(); } } }
▶ Initializer.cs
namespace Visitor { class Initializer:IVisit { public void VisitPicture(Picture picture) { picture.SetInfo(0, 0, 0); } public void VisitDiary(Diary diary) { diary.SetContent("내용 없음"); } } }
25.4.3 MyTour 와 데모 코드
MyTour는 사진과 일기를 보관하는 컬렉션 형식입니다. 여기에서는 사진과 일기 개체를 보관하는 기능과 전체 요소 정보를 보여주는 기능, 전체 요소의 정보를 초기화하는 기능을 제공하려 합니다.
그리고 데모 코드에서는 MyTour 개체에 사진과 일기 개체를 보관한 후에 전체 정보를 보여주고 전체 요소의 정보를 초기화하고 다시 전체 정보를 보여주는 것으로 하겠습니다.
▶ MyTour.cs
using System; using System.Collections.Generic; namespace Visitor { class MyTour { IVisit[] visitors = new IVisit[2]; List<Element> collection = new List<Element>(); public MyTour() { visitors[0] = new Viewer(); visitors[1] = new Initializer(); } public void AddElement(Element element) { collection.Add(element); } public void ViewAll() { foreach (Element element in collection) { element.Accept(visitors[0]); } } public void Reset() { foreach (Element element in collection) { element.Accept(visitors[1]); } Console.WriteLine("모든 정보를 초기 상태로 바꾸었습니다."); } } }
▶ Program.cs
namespace Visitor { class Program { static void Main(string[] args) { MyTour mt = new MyTour(); Picture e = new Picture("A", 1, 1, 1); Diary d = new Diary("2012.6.1", "언제나 휴일"); mt.AddElement(e); mt.AddElement(d); mt.ViewAll(); mt.Reset(); mt.ViewAll(); } } }
▶ 실행 결과
사진 제목:A 색조:1 명도:1 채도:1 2012.6.1 언제나 휴일 모든 정보를 초기 상태로 바꾸었습니다. 사진 제목:A 색조:0 명도:0 채도:0 2012.6.1 내용없음
이상으로 S/W 설계 단계에서 자주 사용되는 GoF의 디자인 패턴에 대해 살펴보았습니다. 앞으로 S/W 개발 시에 설계 단계에서 목적에 맞는 적절한 패턴을 활용할 수 있기를 기대합니다.