● 옵저버 패턴 (Observer Pattern)

 - 한 객체(Subject)의 상태가 바뀌면 그 객체에 의존하는 모든 객체들(Observers)에 알린 후(Notify) 자동으로 내용이 갱신(Update)되는 방식

 - 일대다(one-to-many) 의존성을 정의함

 - MVC 패턴의 View에 해당하는 부분에서 많이 나타날 수 있음 

 - 한 객체의 상태에 대한 참조를 여러 곳에서 하고 있을 때 주로 사용 될 수 있음

 - 때문에, 한 객체의 상태에 대한 일관성이 보장됨



 UML Diagram - Observer Pattern



아주 간단한 예를 들면, (아래의 스크린 샷은 페인트히어로즈의 히어로 선택창스킬 정보창입니다.)

페인트히어로즈에서 현재 선택된 히어로(Subject)가 무엇인지에 따라


이를 의존하고 있던 스킬 정보창의 UI 요소들(Observers - 스킬 이름, 스킬 설명, 스킬 레벨, 스킬 아이콘 등...)이

자동으로 현재 선택된 히어로에 대한 내용으로 갱신되어 유저에게 보여지는 것도 Observer Pattern이 사용될 수 있습니다.




- Source Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Subject.cs
using System.Collections.Generic;
 
public class Subject 
{
    private List<Observer> observerList = new List<Observer>();
 
    public void Attach (Observer o)
    {
        observerList.Add(o);
    }
 
    public void Notify ()
    {
        foreach (Observer o in observerList)
        {
            o.Update();
        }
    }
}
 
 
// SbjHero.cs
public class SbjHero : Subject
{
    private string _heroName;
    private string _heroSkillName;
 
    public string heroName
    {
        get { return _heroName; }
        set { _heroName = value; }
    }
 
    public string heroSkillName
    {
        get { return _heroSkillName; }
        set { _heroSkillName = value; }
    }
}
 
 
// Observer.cs
public abstract class Observer
{
    public abstract void Update ();
}
 
 
// ObsHeroName.cs
using UnityEngine;
 
public class ObsHeroName : Observer 
{
    private SbjHero sbjHero;
 
    public ObsHeroName (SbjHero sbj)
    {
        sbjHero = sbj;
    }
 
    public override void Update ()
    {
        Debug.Log("current hero name : " + sbjHero.heroName);
    }
}
 
 
// ObsHeroSkill.cs
using UnityEngine;
 
public class ObsHeroSkill : Observer 
{
    private SbjHero sbjHero;
 
    public ObsHeroSkill (SbjHero sbj)
    {
        sbjHero = sbj;
    }
 
    public override void Update ()
    {
        Debug.Log("current hero skill name : " + sbjHero.heroSkillName);
    }
}
 
 
// Game.cs
using UnityEngine;
using System.Collections;
 
public class Game : MonoBehaviour 
{
    void Start ()
    {
        SbjHero h = new SbjHero();
 
        h.Attach(new ObsHeroName(h));
        h.Attach(new ObsHeroSkill(h));
 
        // change subject state and notify observers
        h.heroName = "Lucian";
        h.heroSkillName = "Charging Shot";
        h.Notify();
 
        // result
        // current hero name : Lucian
        // current hero skill name : Charging Shot
    }
}
cs


Generic Singleton 패턴 (유니티) 소스코드 입니다.

 - 유니티 app이 종료될 때, 무작위 순서로 오브젝트들이 destroy 됩니다. 
   대체적으로 싱글턴 객체는 app이 종료될 때에만 destroy 되게끔 코딩하는데, 
   OnApplicationQuit에서 싱글턴 객체가 이미 destroy 된 이후에 다른 스크립트에서의 싱글턴 객체 참조를 막기 위해 appIsQuitting 변수를 추가했고
   get부분의 안정성을 위해 lock 키워드로 감싸주었습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// Singleton<T>.cs
using UnityEngine;
using System.Collections;
 
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
    private static T _singleton;
 
    private static object _lock = new object();
 
    private static bool appIsQuitting = false;
 
    public static T singleton
    {
        get
        {
            if (appIsQuitting)
            {
                Debug.LogError("[Singleton<" + typeof(T).ToString() + ">] : " +
                                "already destroyed on application quit");
 
                return null;
            }
 
            lock (_lock)
            {
                if (_singleton == null)
                {
                    _singleton = FindObjectOfType<T>();
 
                    if (FindObjectsOfType(typeof(T)).Length > 1)
                    {
                        Debug.LogError("[Singleton<" + typeof(T).ToString() + ">] : " +
                                        "singleton instance is duplicated");
 
                        return _singleton;
                    }
 
                    if (_singleton == null)
                    {
                        GameObject go = new GameObject();
                        _singleton = go.AddComponent<T>();
                        _singleton.name = typeof(T).ToString();
 
                        DontDestroyOnLoad(_singleton);
                    }
                }
 
                return _singleton;
            }
        }
    }
 
    public virtual void OnApplicationQuit ()
    {
        appIsQuitting = true;
 
        _singleton = null;
    }
 
}
 
 
cs

Singleton 클래스를 'T myClass = new T();' 와 같이 생성자 호출을 통해 생성하는 것을 막으려면
아래처럼 생성자에 protected 지시자를 붙여 주세요.

1
2
3
4
5
6
7
8
// Example - GameManager.cs
public class GameManager : Singleton<GameManager> 
{
    protected GameManager ()
    {
        // guarentee this object will be always a singleton only - can not use the constructor
    }
}
cs

사용 예시

1
2
3
4
5
6
7
8
9
10
11
// Example - Main.cs
using UnityEngine;
using System.Collections;
 
public class Main : MonoBehaviour 
{
    void Awake ()
    {
        Debug.Log(GameManager.singleton.GetType().ToString());
    }
}
cs



'02.Development > Design Pattern' 카테고리의 다른 글

[DesignPattern] Observer Pattern (C#)  (0) 2016.03.15

+ Recent posts