19. 중재자 패턴(Mediator Pattern) 구현

19.4 구현

중재자 패턴에 대한 예제 프로그램을 구현하는 순서는 InnerModue 군, Mediator 군, Camera와 데모 코드순으로 하겠습니다.

19.4.1 InnerModule 군

InnerModule은 Shutter와 Iris의 기반 클래스입니다. 중재자 패턴에서 Shutter 개체와 Iris 개체는 서로에 대한 정보를 알 필요가 없게 하기 위해 중재자의 위치를 알아야 합니다. 그리고, 중재자 패턴에서는 Shutter 개체와 Iris 개체 사이에 주고 받아야 할 상호작용을 해야 하는 것을 중재자 개체에게 전달만 하면 되게 구현해야 합니다. 여기에서는 내부 모듈 개체 생성시에 중재자 개체의 정보를 전달받아 멤버 필드에 보관하게 하였습니다. 그리고, 자신의 값이 변경되면 중재자에게 이 사실을 통보하게 하였습니다.

▶ InnerModule.cs

namespace Mediator
{
    abstract class InnerModule
    {
        IChange mediator;
        public int Mid
        {
            get;
            private set;
        }
        public InnerModule(IChange mediator,int mid)
        {
            Mid = mid;
            this.mediator = mediator;
        }
        public void Changed(int value)
        {
            mediator.Change(Mid,value);
        }
        public abstract void SetValue(int value);
        public abstract void AlramChanged(int value);
    }
}

▶ Shutter.cs

using System;
namespace Mediator
{
    class Shutter:InnerModule
    {
        int speed;
        public Shutter(IChange mediator,int mid):base(mediator,mid)
        {
            speed = 10;
        }
        public override void SetValue(int value)
        {
            this.speed = value;
            Console.WriteLine("셔터 스피드:{0}",speed);
            Changed(speed);
        }
        public override void AlramChanged(int iris)
        {
            Console.WriteLine("조리개 F값 변경 통보 받음");
            SetValue(10 - iris);
        }
    }
}

▶ Iris.cs

using System;
namespace Mediator
{
    class Iris : InnerModule
    {
        int iris;
        public Iris(IChange mediator,int mid):base(mediator,mid)
        {
            iris = 0;
        }
        public override void SetValue(int value)
        {
            this.iris = value;
            Console.WriteLine("조리개 F값:{0}", iris);
            Changed(iris);
        }
        public override void AlramChanged(int speed)
        {
            Console.WriteLine("셔터 스피드 변경 통보 받음");
            SetValue(10 - speed);
        }
    }
}

19.4.2 Mediator 군

IChange에서는 상호작용에 대한 부분을 책임지게 됩니다. 여기에서는 IChange는 인터페이스로 상호작용에 대한 책임을 지게 될 Change 메서드에 대한 약속을 하였습니다. 실제 구체적인 구현은 IChange를 구현 약속하는 클래스인 InnerMediator에서 하고 있습니다. InnerMediator에서는 Iris 개체와 Shutter 개체의 정보를 알고 있습니다. 그리고, 카메라에서 촬영 모드가 변경되면 이를 통보받아 멤버 필드로 보관합니다. 내부 모듈인 Iris 개체나 Shutter 개체에서 값이 변경이 되었음을 통보받으면 촬영 모드를 확인하여 상대 개체에게 이 정보를 전달할 것인지 아닌지를 판단하여 수행하게 됩니다. 중재자 개체를 통해 실제 Iris 개체와 Shutter 개체 사이의 상호작용을 했던 부분을 중재함으로써 둘 사이의 관계를 느슨하게 만들어주는 것입니다.

▶ IChange.cs

namespace Mediator
{
    interface IChange
    {
        void Change(int mid,int value);
    }
}

▶ InnerMediator.cs

namespace Mediator
{
    class InnerMediator:IChange
    {
        InnerModule[] modules = new InnerModule[2];
        int mode;
        public void SetInnerModule(int mid, InnerModule module)
        {
            modules[mid] = module;
        }
        public void ChangeMode(int mode)
        {
            this.mode = mode;
        }
        public void Change(int mid, int value)
        {
            if (mode != mid)
            {
                return;
            }
            if (modules[0].Mid == mid)
            {
                modules[1].AlramChanged(value);
            }
            else
            {
                modules[0].AlramChanged(value);
            }
        }
    }
}

19.4.3 Camera와 데모 코드

Camera는 사용자와 상호작용을 담당합니다. Camera 개체는 내부에 중재자 개체와 내부 모듈인 Shutter 개체와 Iris 개체를 포함하고 있습니다. 사용자가 촬영 모드를 변경하면 중재자에게 전달하고 셔터 스피드를 변경 요청하면 Shutter 개체에게 전달하고 조리개 F값을 변경 요청하면 Iris 개체에게 전달하는 역할을 합니다. 데모 코드에서는 단순히 카메라를 생성하여 셔터 스피드 우선 모드에서 셔터 스피드 값도 변경해 보고 조리개의 F값을 변경도 해 볼 것입니다. 그리고 조리개 우선 모드에서도 셔터 스피드 값도 변경해 보고 조리개의 F값을 변경해 보세요.

▶ Camera.cs 

using System;
namespace Mediator
{
    class Camera
    {
        InnerMediator mediator = new InnerMediator();
        InnerModule[] modules = new InnerModule[2];
        public Camera()
        {            
            modules[0] = new Iris(mediator,0);
            modules[1] = new Shutter(mediator,1);
            mediator.SetInnerModule(0,modules[0]);
            mediator.SetInnerModule(1,modules[1]);
            mediator.ChangeMode(0);
        }
        public void ChangeMode(int mode)
        {
            if((mode != 0)&&(mode!=1))
            {
                return;
            }
            if(mode == 0)
            {
                Console.WriteLine("***   조리개 우선 모드  ***");
            }
            else
            {
                Console.WriteLine("***   셔터 스피드 우선 모드  ***");
            }
            mediator.ChangeMode(mode);
        }
        public void SetIris(int iris)
        {
            modules[0].SetValue(iris);
        }
        public void SetShutterSpeed(int speed)
        {
            modules[1].SetValue(speed);
        }
    }
}

▶ Program.cs 

using System;
namespace Mediator
{
    class Program
    {
        static void Main(string[] args)
        {
            Camera camera = new Camera();
            camera.ChangeMode(0);
            Console.WriteLine( "1");
            camera.SetShutterSpeed(3);
            Console.WriteLine("2");
            camera.SetIris(3);
            camera.ChangeMode(1);
            Console.WriteLine("3");
            camera.SetShutterSpeed(4);
            Console.WriteLine("4");
            camera.SetIris(4);
        }
    }
}

 ▶ 실행 결과

***    조리개 우선 모드    ***
1
셔터 스피드:3
2
조리개 F값:3
조리개 F값 변경 통보 받음
셔터 스피드:7
***    셔터 스피드 우선 모드    ***
3
셔터 스피드:4
셔터 스피드 변경 통보 받음
조리개 F값:6
4
조리개 F값:4