컴퓨터/정보처리기사 SW 공학

| 니앙팽이 - 객체지향(OOP) | 4-7 | 행동패턴 - Observer pattern

객체지향

📕 4. 객체지향 디자인 패턴

유니티에서 사용하면 좋을 디자인 패턴만 명시한다.


📄 5. 행동 패턴

클래스와 객체간 서로 상호작용하는 방법이나 책임 분배 방법을 정의 하나의 객체로 수행할 수 없는작업을 여러 객체로 분해하면서 결합도를 낮출수 있음


2). ✨ Observer Pattern✨

✨매우 중요하므로 대리자 & 이벤트 에서 정리✨

ⓐ 특징

  • 이벤트기반 패턴이다. 디커플링에 매우 유용
  • 옵서버 패턴은 여러 객체에 자신이 관찰 중인 객체에 발생하는 모든 이벤트에 대하여 알리는 구독 메커니즘을 정의할 수 있도록 하는 행동 디자인 패턴입니다.

ⓑ 왜 쓰는가?

  • 옵서버 패턴은 한 객체의 상태가 변경되어 다른 객체들을 변경해야 할 필요성이 생겼을 때, 그리고 실제 객체 집합들을 미리 알 수 없거나 이러한 집합들이 동적으로 변경될 때 사용하세요.

  • 손님들이 신제품 출시 확인을 위해 시간을 낭비하든지, 매장들이 알림을 원하지 않는 고객들에게 신제품 출시를 알리는 이 두가지 문제를 어떻게 해결할까?


1. 아이폰이 출시될 예정이라는 얘기를 듣고 가게에 들어왔나 안들어왔나 왔다갔다하면서 뻉이 치는중
2. 아이폰 출시를 모두한테 알리는데, 만약 관심 없는 사람한테도 알림이 간다면? 스팸메일이 될것이다.

ⓒ 구성요소

  • Subject = Publisher :

    • 시간이 지나면 병경 될 수 있는 객체
    • 자신의 상태에 변경에 대해서 다른 객체들에게 알림을 보내는 역할도 한다.
    • Observer(Subscriber) 리스트를 가지고 있다.
      • 이벤트가 발생할 때 마다 Observer(Subscriber) 리스트를 참조한다
    • Observer(Subscriber) 가 구독 또는 구독 취소를 할 수 있는 매커니즘을 가진 구독자 객체
  • Observer = Subscriber :

    • Subscriber(Publisher)가 만드는 알림을 받는 객체
    • 알림을 받으면 실행될 Update를 가진 인터페이스로 구현한다.
    • 이 객체를 상속받으면 ConcreteObserver(ConcreteSubscriver)가 된다.
  • 클라이언트

    • 클라이언트는 Subject 와 Observer 객체를 별도로 생성하고 Observer를 Subject에 등록한다.

ⓓ 예시

📂Observer Pattern 정석적인 예시 (C#)📂
using System;
using System.Collections;
using System.Collections.Generic;

namespace DesignPattern
{
    /*
    *
    */
    interface Observer {
        public void Update();
    }

    class Subject {
        List<Observer> mObservers = new List<Observer>();

        public void Register(Observer _observer) {
            mObservers.Add(_observer);
        }

        public void Unregister(Observer _observer){
            mObservers.Remove(_observer);
        }

        public void AlertToObservers(){
            foreach(Observer E in mObservers){E.Update();}
        }
    }

    /*
    * Concrete
    */
    class ConcreteObserver_Cat : Observer {
        public void Update() {
            Console.WriteLine("Meow");
        }
    }
    class ConcreteObserver_Dog : Observer {
        public void Update() {
            Console.WriteLine("Bark");
        }
    }
    class Owner : Subject {}
    /*
    * Client.cs
    */
    static void Main(string argv){
        Owner owner = new Owner();
        ConcreteObserver_Cat cat = new ConcreteObserver_Cat();
        ConcreteObserver_Dog dog = new ConcreteObserver_Dog();

        owner.Register(cat);  owner.Register(dog);
        owner.AlertToObservers();
        owner.Unregister(cat);
        owner.AlertToObservers();
    } 
}
📂Observer Pattern 홀짝 게임 (C#)📂
using System;
using System.Collections;
using System.Collections.Generic;

namespace DesignPattern
{
    public abstract class Observer_Player {
        private String name;

        public Observer_Player(String _name) {
            this.name = _name;
        }

        public String Name {get{return this.name;}}

        public abstract void Update(int diceNumber);
    }

    public abstract class Subject_DiceGame {
        protected List<Observer_Player> playerList = new List<Observer_Player>();

        public void AddPlayer(Observer_Player player){
            playerList.Add(player);
        }

        public abstract void Play();
    }

    public class ConcreteSubject_FairDiceGame : Subject_DiceGame {
        private Random random = new Random();

        public override void Play()
        {
            int diceNumber = random.Next(6) + 1;
            Console.WriteLine($"주사위눈 : {this.diceNumber}");

            foreach(Observer_Player E in playerList){
                E.Update(diceNumber);
            }
        }
    }

    public class ConcreteObserver_EvenBattingPlayer : Observer_Player
    {
        public ConcreteObserver_EvenBattingPlayer(String _name) : base(_name) { }
        public override void Update(int diceNumber)
        {
            if (diceNumber % 2 == 0) { Console.WriteLine("짝수 당첨"); }
        }
    }
    public class ConcreteObserver_OddBattingPlayer : Observer_Player
    {
        public ConcreteObserver_OddBattingPlayer(String _name) : base(_name) { }
        public override void Update(int diceNumber)
        {
            if (diceNumber % 2 != 0) { Console.WriteLine("홀수 당첨"); }
        }
    }

    public static void main(String[] args){
        Subject_DiceGame diceGame = new ConcreteSubject_FairDiceGame();

        ArrayList<Observer_Player> player = new ArrayList<Observer_Player>();
        player.Add(new ConcreteObserver_EvenBattingPlayer("짝궁둥이"));
        player.Add(new ConcreteObserver_OddBattingPlayer("홀아비"));
        player.Add(new ConcreteObserver_OddBattingPlayer("홀쭉이"));

        foreach(Observer_Player E in player){
            diceGame.AddPlayer(E);
        }

        for(int i = 0; i< 5; i++){
            diceGame.Play();
            Console.WriteLine();
        }
    }
}

ⓔ Unity also has its own implementation.

  1. EventHandler 2. Action 3. UnityEvent 4. delegate
  2. 자기 자신과 관계없는 함수와 연결시켜줄 수 있다.