[TIL] Manager 설계

Dreamer·2024년 11월 14일

1. 오늘 주제

Manager를 설계하는 방법에 대해 생각해보고자 한다.

회사마다 사람마다 설계하는 방식이 모두 다르지만 의도는 거의 동일하기 때문에 어떻게 설계를 하든 상관은 없다만 요즘 설계 방식도 재밌어 보여서 남겨본다.

2. 코드

  1. 기존 설계
  • 기존에는 설계 방식은 매니저들은 싱글톤을 상속받아 어디서든 독립적으로 사용하도록 하는것이 기존에 설계방식이다.
    • 장점 : 무지성으로 만들고 사용할 수 있다.
    • 단점 : 무지성으로 만들고 사용할 수 있다.
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
    private static T instance;
    public static T Instance { get { SingletonInit(); return instance; } }

    private static void SingletonInit()
    {
        if (instance == null)
        {
            instance = new GameObject(typeof(T).Name).AddComponent<T>();
            if (Application.isPlaying)
                DontDestroyOnLoad(instance.gameObject);
        }
    }
}

public class GameManager : Singleton<GameManager>
{
	// ...
}
  1. 요즘 유행한다는 방식
  • 요즘에는 상위 관리자가 있으면 하위 관리자에게 상위 관리자에게 역참조를 걸어 의존성 주입하는 형식으로 사용한다.
    • 장점 : 외부에서 의존성을 줄일 수 있다.
    • 단점 : 역참조를 하기 때문에 다소 복잡하게 느껴질지도 모르겠다.
public class GameManager : MonoBehaviour, IGameManager
{
	[SerializeField]
	private CharacterManager _characterManager;
    
    // ..
}

// GameManager의 하위 관리자는 GameManager로의 역참조를 갖도록 한다.
public class CharacterManager : MonoBehaviour
{
	private IGameManager _gameManager;
	private List<BaseCharacter> _guardians = new List<BaseCharacter>();
    
	public IGameManager GameManager
	{
		get { return _gameManager; }
	}
	
	public void Init(IGameManager gameManager)
	{
		_gameManager = gameManager;
	}
	// ..
}

// CharacterManager의 하위 객체는 CharacterManager로의 역참조를 갖는다. 
// 이렇게 되면 모든 객체는 다른 모든 객체를 참조해올 수 있다.
public class BaseCharacter : MonoBehaviour
{
	protected CharacterManager _manager;
	public void Init(CharacterManager manager)
	{
		_manager = manager;
	}
}
  1. 개인적으로 선호하는 방식
  • 개인적으로 선호하는 방식은 Managers를 하나의 GameObject Component로 두고 그 안에서 MonoBehaviour 아닌 그냥 일반 클래스를 인스턴스화 하여 Managers에서 여러 매니저를 사용 할 수 있도록 한다.
    • 장점 : 매니저 오브젝트가 하나만 생긴다. 공통적으로 관리할 수 있다.
    • 단점 : 매니저 안에서 MonoBehaviour 기능은 사용할 수 없다. 예를 들면 코루틴
public interface IManager
{
    void Init();
    void Clear();
}

public class Managers : MonoBehaviour
{
	
    private static Managers instance;
    public static Managers Instance
    {
        get
        {
            Initialize();
            return instance;
        }
    }
    
    private static void Initialize() 
    {
    	if (instance == null)
        {
        	instance = new GameObject($"@Managers").AddComponent<Managers>();
            DontDestroyOnLoad(instance.gameObject);
        }
    }
    
    private DBManager _db = new DBManager();
    public static DBManager DB
    {
        get { return Instance?._db; }
    }
}

public class DBManager : IManager
{
	public void Init()
    {
    	
    }
    public void Clear()
    {
        
    }
    // ...
}

일단 3가지 정도 예시를 들었지만, 결국에는 본인이 편한쪽으로 설계하는 것이 맞는 것 같다. 하지만 결국에는 회사에서 일을 하게 되면 회사에 맞게 하는 편이 좋겠지..

profile
새로운 시작

0개의 댓글