본문 바로가기

Design Pattern/GOF(Gang Of Four)

C# - 옵저버 패턴(Observer Pattern)

1. 정의

ㆍ주제대상(Subject) - 관찰자(Observer)간의 일대다(One-To-Many) 관계.

주제 대상이 불특정 다수의 관찰자에게 통보.

ㆍ낮은 결합도(커플링).

ㆍ게시-구독(Publish-Subscribe) 관계

한 객체의 상태가 바뀌면 그 객체를 참조하고 있는 다른 객체들에게도 자동으로 바뀐 내용이 갱신되어야 합니다.

 

순서도

Concrete : 구상된(생성된) 객체.


2. 구현

유튜브의 구독과 푸시 알림을 게시-구독 관계로 구현해보고자 합니다.

순서도

※ 인터페이스 설정

- 구독정보(Subject)

// 유튜버가 구현해야할 구독시스템.
public interface SubscribeInfo
{
    // 구독
    public void Subscribe(Subscriber subscriber);
    // 구독 취소
    public void Unsubscribe(Subscriber subscriber);
    // 알람 보내기
    public void PushAlarm();
}

 

- 구독자(Observer)

// 구독자가 구현해야할 인터페이스
public interface Subscriber
{
    // 알람 받기
    public void PullAlarm(SubscribeInfo subscribe);
}

※ 유튜버 설정

public class Youtuber : SubscribeInfo
{
    // 구독자 관리를 위한 List
    List<Subscriber> subscribers = new List<Subscriber>();

    // 알림메세지 정보
    public string? videoName {get; private set;}
    public int uploadHour{get; private set;}
    public int uploadMinute { get; private set; }

    // 구독자 추가
    public void Subscribe(Subscriber subscriber)
    {
        subscribers.Add(subscriber);
    }

    // 구독 취소
    public void Unsubscribe(Subscriber subscriber)
    {
        if(subscribers.Count != 0)
        {
            subscribers.Remove(subscriber);
        }
    }

    // 알람 보내기
    public void PushAlarm()
    {
        // 구독자들에게 알람 정보를 담고있는 자신을 변수로 알람을 보낸다.
        for(int i = 0; i < subscribers.Count; i++)
        {
            Subscriber subscriber = subscribers[i];
            subscriber.PullAlarm(this);
        }
    }

    // 알람 메세지 작성
    public void SetPushText(string name, int hour, int minute)
    {
        videoName = name;
        uploadHour = hour;
        uploadMinute = minute;
    }
}

※ 구독자 설정

public class Viewer : Subscriber
{
    Youtuber subscribeChannel;      // 구독할 채널
    string viewerName;              // 구독자 이름

    // 생성될 때, 구독자 이름과 구독할 채널을 갖는다.
    public Viewer(Youtuber subscribeChannel, string viewerName)
    {
        this.viewerName = viewerName;
        this.subscribeChannel = subscribeChannel;
        subscribeChannel.Subscribe(this);
    }

    public void PullAlarm(SubscribeInfo subscribeInfo)
    {
        // 변수로 받아온 구독 정보가 Youtuber라면 if문의 내용을 실행시킨다.
        if(subscribeInfo is Youtuber youtube)
        {
            Console.WriteLine($"{viewerName}님. 영상 \"{youtube.videoName}\"이 업로드 됐습니다. 업로드 시간 = {youtube.uploadHour} : {youtube.uploadMinute}");
        }
    }

    // 구독 취소
    public void CancelSubscribe()
    {
        subscribeChannel.Unsubscribe(this);
    }
}

※ 출력 확인

    public static void Main()
    {
	// 구독할 채널과 구독자를 생성한다.
        Youtuber youtuber = new Youtuber();
        Viewer viewer1 = new Viewer(youtuber, "구독자1");
        Viewer viewer2 = new Viewer(youtuber, "구독자2");
        Viewer viewer3 = new Viewer(youtuber, "구독자3");

        Console.WriteLine("[유튜버가 알람 메세지를 작성하고 알람을 보낸다.]");
        youtuber.SetPushText("테스트 영상1", 12, 34);
        youtuber.PushAlarm();

        Console.WriteLine("");

        Console.WriteLine("[두번째 구독자가 구독 취소를 한 뒤 알람을 보낸다.]");
        youtuber.SetPushText("테스트 영상2", 48, 85);
        viewer2.CancelSubscribe();
        youtuber.PushAlarm();
    }

 

정상적으로 출력 완료

 

'Design Pattern > GOF(Gang Of Four)' 카테고리의 다른 글

C# - 전략 패턴(Strategy Pattern)  (0) 2022.08.24