ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [C#] Observer Pattern
    프로그래밍/Design Pattern 2020. 10. 30. 10:45

     옵저버 패턴이란

    한 객체의 상태 변화에 따라 다른 객체의 상태도 연동되도록 일대다 객체 의존 관계를 구성하는 패턴.

    그림으로 보겠습니다.

     

     

     

     

    옵저버 패턴은 크게 Subject 하나와

    다수의 Observer 로 구성되어 있습니다.

     

    쉬운 예시를 들자면 Subject 는 유투브 채널

    Observer 는 구독자가 되겠습니다.

     

    요러한 일대다의 관계를 표현하고자 할때

    유용한 패턴이 옵저버 패턴입니다.

     

    코드 설계도를 봅시다.

     

     

     

     

     

     

     

    위에 있는 Subject 와 Observer 는 인터페이스를 의미합니다.

    Abstract 클래스를 의미하죠.

     

     

    아래에 있는 Concreate 함수는 필수 인터페이스를

    상속받는 파생 클래스로 보시면 되겠습니다.

     

     

    우리는 Concreate 클래스로

    주제와 옵저버를 각각 생성하고

    구독, 취소, 전파

    하는 과정을 보고 구현해보도록 해보겠습니다.

     

     

    다시 유튜브를 예로 들어서 봅시다.

    Subject = Channel

    Observer = Subscriber

     

    이렇게 채널과 구독자의 관계를 구현해보겠습니다.

     

     

     

    채널의 인터페이스 입니다.

    구독자들을 저장해둘 LIST 컨테이너.

    구독자들을 추가하는 Subscribe 메서드.

    구독을 취소하는 Cancel 메서드.

    정보를 전파하는 Notify 메서드.

     

    여기까지가 채널이 가져야 하는 필수 구성 사항이

    되고 이 인터페이스를 참조해서 채널을 생성하게 됩니다.

     

     

     

     

     

     

     

     

    ConcreateChannel 클래스는 보시는 것처럼

    Channel 클래스를 참조하기 때문에

    굳이 override 하지 않아도 부모 클래스의

    메서드 사용이 가능합니다.

     

    그리고 채널의 상태를 주고받는

    getter, setter 를 만들어 줍시다.

     

     

     

    Observer 의 인터페이스입니다.

     

     

     

     

     

     

    생성자와 변수들의 getter, setter

    그리고 update 메서드의 오버라이드가

    보입니다.

     

    여기까지 보면서 눈여겨보셔야 할 부분이

    옵저버 패턴은 느슨한 결합을 

    중요시하는 구조라는 겁니다.

     

    두 클래스가 분명 연결되어 있지만

    그 연결을 아주 최소화하고 있는 것을

    볼 수 있습니다.

     

    아래에 전체 코드가 있습니다.

     

     

     

     

     

     

     

     

    using System;
    using System.Collections.Generic;
    
    namespace DoFactory.GangOfFour.Observer.Structural
    {
    
        class MainApp
    
        {
            static void Main()
            {
                ConcreateChannel JoonTV = new ConcreateChannel();
    
                ConcreateSubscriber A = new ConcreateSubscriber(JoonTV, "A");
                ConcreateSubscriber B = new ConcreateSubscriber(JoonTV, "B");
                ConcreateSubscriber C = new ConcreateSubscriber(JoonTV, "C");
    
                JoonTV.Subscibe(A);
                JoonTV.Subscibe(B);
                JoonTV.Subscibe(C);
    
                JoonTV.ChannelState = "Subscibe 3";
                JoonTV.Notify();
                Console.WriteLine('\n');
    
                JoonTV.Cancel(A);
                JoonTV.ChannelState = "Subscibe 2";
                JoonTV.Notify();
    
    
            }
        }
    
        abstract class Channel
        {
            private List<Subscriber> _subscribers = new List<Subscriber>();
    
            public void Subscibe(Subscriber subscriber)
            {
                _subscribers.Add(subscriber);
            }
    
            public void Cancel(Subscriber s)
            {
                _subscribers.Remove(s);
            }
    
            public void Notify()
            {
                foreach(Subscriber s in _subscribers)
                {
                    s.Update();
                }
            }
    
        }
    
        class ConcreateChannel : Channel
        {
            private string _channelState;
    
            public string ChannelState
            {
                get { return _channelState; }
                set { _channelState = value; }
            }
    
        }
    
        abstract class Subscriber
        {
            public abstract void Update();
        }
    
        class ConcreateSubscriber : Subscriber
        {
            private string _name;
            private string _channelState;
            private ConcreateChannel _channel;
    
            public ConcreateSubscriber(ConcreateChannel channel, string name)
            {
                _name = name;
                _channel = channel;
            }
    
            public override void Update()
            {
                _channelState = _channel.ChannelState;
                Console.WriteLine("Channel {0}'s new state is {1}",
                    _name, _channelState);
            }
    
            public ConcreateChannel Channel
            {
                get { return _channel; }
                set { _channel = value; }
            }
    
            public string name
            {
                get { return _name; }
                set { _name = value; }
            }
        }
    
    }

     

     

     

     

     

     

     

     

     

     

     

     

     

    '프로그래밍 > Design Pattern' 카테고리의 다른 글

    [C#] Decorator Pattern  (0) 2020.11.06
    [C#] Strategy Pattern  (0) 2020.10.23

    댓글

Designed by Tistory.