본문 바로가기

Unity/Unity 스파르타

디자인 패턴에 대한 고찰(1) - 싱글턴

728x90

디자인패턴, 싱글턴에 대해 알아보고 이에 대해 고찰해 보자..

 

싱글턴패턴은 인스턴스가 오직 하나만 생성됨으로 인스턴스의 유일성을 보장해 항상 동일한 인스턴스를 사용할 수 있습니다. 

또한 전역적 접근으로 어디서든 동일한 인스턴스에 접근해 코드의 유연성과 확장성을 향상 시킬 수 있습니다 .

하지만 항상 주의 해야할 점은 싱글턴패턴의 클래스의 인스턴스는 무조건 1개만 존재해야하며 전역적으로 관리하기 때문에 싱글턴 패턴의 클래스가 많아질 수록 메모리 누수 문제와 성능상 좋지않은 영향을 줄 가능성이 높습니다.

 

일반적인 싱글턴 

public class SingletonExample : MonoBehaviour
{
    private static SingletonExample _instance;

    public static SingletonExample Instance
    {
        get
        {
            // 인스턴스가 없을 경우 새로 생성합니다.
            if (_instance == null)
            {
                // Scene에서 이미 있는지 확인하고 없으면 생성합니다.
                _instance = FindObjectOfType<SingletonExample>();

                // Scene에 존재하지 않는 경우 새로운 GameObject를 생성하여 싱글턴 인스턴스를 추가합니다.
                if (_instance == null)
                {
                    GameObject singletonObject = new GameObject();
                    _instance = singletonObject.AddComponent<SingletonExample>();
                    singletonObject.name = "SingletonExample";
                    DontDestroyOnLoad(singletonObject);
                }
            }
            return _instance;
        }
    }

    private void Awake()
    {
        // 이미 싱글턴 인스턴스가 존재하면 새로 생성된 인스턴스를 파괴합니다.
        if (_instance != null && _instance != this)
        {
            Destroy(this.gameObject);
        }
    }

싱글턴 활용 심화 

아래 코드는 인스펙터에 싱글턴 매니저 오브젝트들을 하나하나 다 만들지 않고 하나의 매니저에서 한번에 관리하기 위한 코드 입니다.

좋은점은 인스펙터창이 깔끔해지고 다른 매니저급 클래스들을 관리하고 사용하기 좋습니다.

특히, Scene 마다 사용 되어져야하는 UI 의 경우에 매우 용이합니다.

허나, 아래 매니저 클래스에서는 매니저급 클래스를 New 생성자를 통해 만들어 지고있기 때문에 해당 매니저급 클래스에서는 MonoBehaviour 를 상속 받을 수 없습니다. 그렇게 때문에 주로 프리팹화 해놓은 리소스폴더 내의 프리팹 파일을 불러와 사용하게 됩니다.

그래서 아래 매니저 클래스에서 사용될, 특히 UI매니저의 경우에는 구조적으로 설계할 필요성이 있습니다.

매우 번거로운 과정일 수 있지만 인스펙터창을 매우 깨끗하게, 효율적으로 관리할 수 있다는 장점이 있습니다.

ex)UI_Base(해당 UI의 특정 컴포넌트들을 딕셔너리로 담아 사용가능한 클래스) -> UI_Popup(UI에 그래픽요소들을 관리) ->UIManager(캔버스 생성및 UI생성)

public class Manager : MonoBehaviour
{
    static Manager _instance;
    static Manager Instance { get { Init(); return _instance; } }

    GameManager _gameManager = new GameManager();
    UIManaer _uiManager = new UIManaer();
    
    public static GameManager GameManager => Instance?._gameManager;
    public static UIManaer UI => Instance?._uiManager;
    
    private void Awake()
    {
        Init();
    }


    private static void Init()
    {
        if (_instance == null)
        {
            GameObject go = GameObject.Find("@Managers");

            if (go == null)
            {
                go = new GameObject("@Managers");
                go.AddComponent<Manager>();
            }
            DontDestroyOnLoad(go);
            _instance = go.GetComponent<Manager>();
        }
    }
}
728x90