๐Ÿ“š Computer Science/Design Pattern

[Unity][๋””์ž์ธ ํŒจํ„ด] Observer Pattern

ibelieveinme 2023. 9. 3. 23:19
728x90

ํ•œ ๊ฐ์ฒด์˜ ์ƒํƒœ๊ฐ€ ๋ฐ”๋€Œ๋ฉด ๊ทธ ๊ฐ์ฒด์— ์˜์กดํ•˜๋Š” ๋‹ค๋ฅธ ๊ฐ์ฒด๋“ค์—๊ฒŒ ์—ฐ๋ฝ์ด ๊ฐ€๊ณ  ์ž๋™์œผ๋กœ ๋‚ด์šฉ์ด ๊ฐฑ์‹ ๋˜๋Š” ๋ฐฉ์‹.

์ฃผ์ œ์™€ ์˜ต์ €๋ฒ„๊ฐ€ ๋Š์Šจํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋˜์–ด ์žˆ๋Š” ๊ฐ์ฒด ๋””์ž์ธ.

 

Subject๊ฐ€ Observer์— ๋Œ€ํ•ด์„œ ์•„๋Š” ๊ฒƒ์€ Observer๊ฐ€ ํŠน์ • ์ธํ„ฐํŽ˜์ด์Šค(Observer ์ธํ„ฐํŽ˜์ด์Šค)๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค๋Š” ๊ฒƒ ๋ฟ.

 

Observer๋Š” ์–ธ์ œ๋“ ์ง€ ์ƒˆ๋กœ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Œ.

์ƒˆ๋กœ์šด ํ˜•ํƒœ์˜ Observer๋ฅผ ์ถ”๊ฐ€ํ•˜๋ ค ํ•ด๋„ Subject๋ฅผ ์ „ํ˜€ ๋ณ€๊ฒฝํ•  ํ•„์š”๊ฐ€ ์—†์Œ.

์ƒˆ๋กœ์šด ํด๋ž˜์Šค์—์„œ Observer ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ๊ตฌํ˜„ํ•ด์ฃผ๋ฉด ๋จ.

 

Subject๋‚˜ Observer๊ฐ€ ๋ฐ”๋€Œ๋”๋ผ๋„ ์„œ๋กœ์—๊ฒŒ ์ „ํ˜€ ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Œ. ๊ทธ๋ž˜์„œ Subject์™€ Observer๋Š” ์„œ๋กœ ๋…๋ฆฝ์ ์œผ๋กœ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ.

 

1. ๊ธฐ๋ณธ ํ˜ธ์ถœ

//์˜ต์ €๋ฒ„ ์ถ”์ƒํด๋ž˜์Šค
//: ์˜ต์ €๋ฒ„๋“ค์ด ๊ตฌํ˜„ํ•ด์•ผ ํ•  ์ธํ„ฐํŽ˜์ด์Šค ๋ฉ”์„œ๋“œ
public abstract class Observer
{
    public abstract void OnNotify();
}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//์˜ต์ €๋ฒ„ ๊ตฌํ˜„ํด๋ž˜์Šค
public class ConcreteObserver1 : Observer
{
    //๋Œ€์ƒํƒ€์ž…์˜ ํด๋ž˜์Šค์—์„œ ์ด ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰์‹œํ‚ด
    public override void OnNotify()
    {
        Debug.Log("์˜ต์ €๋ฒ„ ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ ์‹คํ–‰ #1");
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//์˜ต์ €๋ฒ„ ๊ตฌํ˜„ํด๋ž˜์Šค
public class ConcreteObserver2 : Observer
{
    //๋Œ€์ƒํƒ€์ž…์˜ ํด๋ž˜์Šค์—์„œ ์ด ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰์‹œํ‚ด
    public override void OnNotify()
    {
        Debug.Log("์˜ต์ €๋ฒ„ ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ ์‹คํ–‰ #2");
    }
}

 

//๋Œ€์ƒ ์ธํ„ฐํŽ˜์ด์Šค
//: ์˜ต์ €๋ฒ„ ๊ด€๋ฆฌ, ํ™œ์šฉ์— ๊ด€ํ•œ ํƒ€์ž… ์ •์˜
public interface ISubject
{
    void AddObserver(Observer o);
    void RemoveObserver(Observer o);
    void Notify();
}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//๋Œ€์ƒ ํด๋ž˜์Šค
//: ๋Œ€์ƒ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค
public class ConcreteSubject : MonoBehaviour, ISubject
{
    List<Observer> observers = new List<Observer>(); //์˜ต์ €๋ฒ„๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” List
    
    //๊ด€๋ฆฌํ•  ์˜ต์ €๋ฒ„๋ฅผ ๋“ฑ๋ก
    public void AddObserver(Observer observer)
    {
        observers.Add(observer);
    }
    
    //๊ด€๋ฆฌ์ค‘์ธ ์˜ต์ €๋ฒ„๋ฅผ ์‚ญ์ œ
    public void RemoveObserver(Observer observer)
    {
        if(observers.IndexOf(observer) > 0) observers.Remove(observer);
    }
    
    //๊ด€๋ฆฌ์ค‘์ธ ์˜ต์ €๋ฒ„์—๊ฒŒ ์—ฐ๋ฝ
    public void Notify()
    {
        foreach(Observer o in observers)
        {
            o.OnNotify();
        }
    }
    
    void Start()
    {
        Observer obj1 = new ConcreteObserver1();
        Observer obj2 = new ConcreteObserver2();
        
        AddObserver(obj1);
        AddObserver(obj2);
    }
}

 

2. ํ˜ธ์ถœ & ๊ฐ’ ๋„˜๊ธฐ๊ธฐ: ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌํ•˜๋Š” ์ „ํ†ต์ ์ธ ๋ฐฉ๋ฒ•

//์˜ต์ €๋ฒ„ ์ถ”์ƒํด๋ž˜์Šค
//: ์˜ต์ €๋ฒ„๋“ค์ด ๊ตฌํ˜„ํ•ด์•ผ ํ•  ์ธํ„ฐํŽ˜์ด์Šค ๋ฉ”์„œ๋“œ
public abstract class Observer
{
    public abstract void OnNotify(int num);
}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//์˜ต์ €๋ฒ„ ๊ตฌํ˜„ํด๋ž˜์Šค
public class ConcreteObserver1 : Observer
{
    //๋Œ€์ƒํƒ€์ž…์˜ ํด๋ž˜์Šค์—์„œ ์ด ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰์‹œํ‚ด
    public override void OnNotify(int num)
    {
        Debug.Log($"์˜ต์ €๋ฒ„ ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ ์‹คํ–‰ #1 : {num}");
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//์˜ต์ €๋ฒ„ ๊ตฌํ˜„ํด๋ž˜์Šค
public class ConcreteObserver2 : Observer
{
    //๋Œ€์ƒํƒ€์ž…์˜ ํด๋ž˜์Šค์—์„œ ์ด ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰์‹œํ‚ด
    public override void OnNotify(int num)
    {
        Debug.Log($"์˜ต์ €๋ฒ„ ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ ์‹คํ–‰ #2 : {num}");
    }
}

 

//๋Œ€์ƒ ์ธํ„ฐํŽ˜์ด์Šค
//: ์˜ต์ €๋ฒ„ ๊ด€๋ฆฌ, ํ™œ์šฉ์— ๊ด€ํ•œ ํƒ€์ž… ์ •์˜
public interface ISubject
{
    void AddObserver(Observer o);
    void RemoveObserver(Observer o);
    void Notify();
}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//๋Œ€์ƒ ํด๋ž˜์Šค
//: ๋Œ€์ƒ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค
public class ConcreteSubject : MonoBehaviour, ISubject
{
    List<Observer> observers = new List<Observer>(); //์˜ต์ €๋ฒ„๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” List
    private int myNum; //์˜ต์ €๋ฒ„์—๊ฒŒ ์ „๋‹ฌํ•  ๊ฐ’
    
    //๊ด€๋ฆฌํ•  ์˜ต์ €๋ฒ„๋ฅผ ๋“ฑ๋ก
    public void AddObserver(Observer observer)
    {
        observers.Add(observer);
    }
    
    //๊ด€๋ฆฌ์ค‘์ธ ์˜ต์ €๋ฒ„๋ฅผ ์‚ญ์ œ
    public void RemoveObserver(Observer observer)
    {
        if(observers.IndexOf(observer) > 0) observers.Remove(observer);
    }
    
    //๊ด€๋ฆฌ์ค‘์ธ ์˜ต์ €๋ฒ„์—๊ฒŒ ์—ฐ๋ฝ & ๊ฐ’ ์ „๋‹ฌ
    public void Notify()
    {
        foreach(Observer o in observers)
        {
            o.OnNotify(int num);
        }
    }
    
    void Start()
    {
        myNum = 10;
        
        Observer obj1 = new ConcreteObserver1();
        Observer obj2 = new ConcreteObserver2();
        
        AddObserver(obj1);
        AddObserver(obj2);
    }
}

 

3. ํ˜ธ์ถœ & ๊ฐ’ ๋„˜๊ธฐ๊ธฐ: ์˜ต์ €๋ฒ„๋ฅผ ์ƒ์„ฑํ•  ๋•Œ Subject๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ฒจ์ฃผ๋Š” ๋ฐฉ๋ฒ•

//์˜ต์ €๋ฒ„ ์ถ”์ƒํด๋ž˜์Šค
//: ์˜ต์ €๋ฒ„๋“ค์ด ๊ตฌํ˜„ํ•ด์•ผ ํ•  ์ธํ„ฐํŽ˜์ด์Šค ๋ฉ”์„œ๋“œ
public abstract class Observer
{
    public abstract void OnNotify();
}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//์˜ต์ €๋ฒ„ ๊ตฌํ˜„ํด๋ž˜์Šค
public class ConcreteObserver1 : Observer
{
    GameObject obj;
    
    //์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด ์ „๋‹ฌ
    public ConcreteObserver1(GameObject obj)
    {
        this.obj = obj;
    }
    
    //๋Œ€์ƒํƒ€์ž…์˜ ํด๋ž˜์Šค์—์„œ ์ด ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰์‹œํ‚ด
    public override void OnNotify()
    {
    	int num = obj.gameObject.GetComponent<ConcreteSubject>().GetNum();
        Debug.Log($"์˜ต์ €๋ฒ„ ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ ์‹คํ–‰ #1 : {num}");
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//์˜ต์ €๋ฒ„ ๊ตฌํ˜„ํด๋ž˜์Šค
public class ConcreteObserver2 : Observer
{
    GameObject obj;
    
    //์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด ์ „๋‹ฌ
    public ConcreteObserver2(GameObject obj)
    {
        this.obj = obj;
    }
    
    //๋Œ€์ƒํƒ€์ž…์˜ ํด๋ž˜์Šค์—์„œ ์ด ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰์‹œํ‚ด
    public override void OnNotify()
    {
    	int num = obj.gameObject.GetComponent<ConcreteSubject>().GetNum();
        Debug.Log($"์˜ต์ €๋ฒ„ ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ ์‹คํ–‰ #2 : {num}");
    }
}

 

//๋Œ€์ƒ ์ธํ„ฐํŽ˜์ด์Šค
//: ์˜ต์ €๋ฒ„ ๊ด€๋ฆฌ, ํ™œ์šฉ์— ๊ด€ํ•œ ํƒ€์ž… ์ •์˜
public interface ISubject
{
    void AddObserver(Observer o);
    void RemoveObserver(Observer o);
    void Notify();
}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//๋Œ€์ƒ ํด๋ž˜์Šค
//: ๋Œ€์ƒ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค
public class ConcreteSubject : MonoBehaviour, ISubject
{
    List<Observer> observers = new List<Observer>(); //์˜ต์ €๋ฒ„๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” List
    private int myNum; //์˜ต์ €๋ฒ„์—๊ฒŒ ์ „๋‹ฌํ•  ๊ฐ’
    
    //๊ด€๋ฆฌํ•  ์˜ต์ €๋ฒ„๋ฅผ ๋“ฑ๋ก
    public void AddObserver(Observer observer)
    {
        observers.Add(observer);
    }
    
    //๊ด€๋ฆฌ์ค‘์ธ ์˜ต์ €๋ฒ„๋ฅผ ์‚ญ์ œ
    public void RemoveObserver(Observer observer)
    {
        if(observers.IndexOf(observer) > 0) observers.Remove(observer);
    }
    
    //๊ด€๋ฆฌ์ค‘์ธ ์˜ต์ €๋ฒ„์—๊ฒŒ ์—ฐ๋ฝ & ๊ฐ’ ์ „๋‹ฌ
    public void Notify()
    {
        foreach(Observer o in observers)
        {
            o.OnNotify();
        }
    }
    
    void Start()
    {
        myNum = 10;
        
        Observer obj1 = new ConcreteObserver1(this.gameObject);
        Observer obj2 = new ConcreteObserver2(this.gameObject);
        
        AddObserver(obj1);
        AddObserver(obj2);
    }
    
    public int GetNum()
    {
        return myNum;
    }
}

 

728x90