디자인 패턴에 대한 고찰(1) - 싱글턴
디자인패턴, 싱글턴에 대해 알아보고 이에 대해 고찰해 보자..
싱글턴패턴은 인스턴스가 오직 하나만 생성됨으로 인스턴스의 유일성을 보장해 항상 동일한 인스턴스를 사용할 수 있습니다.
또한 전역적 접근으로 어디서든 동일한 인스턴스에 접근해 코드의 유연성과 확장성을 향상 시킬 수 있습니다 .
하지만 항상 주의 해야할 점은 싱글턴패턴의 클래스의 인스턴스는 무조건 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>();
}
}
}