Singleton 패턴이란?

 싱글톤 패턴은 런타임 동안 단 하나의 인스턴스만을 생성하는 패턴을 의미한다. 싱글톤 패턴이 적용된 객체는 하나의 인스턴스만 생성할 수 있으며 다른 객체에서 싱글톤 객체의 인슨턴스를 생성하려 할 경우 기존에 생성된 인스턴스가 있다면 해당 인스턴스를 반환하는 형태이다.

 

Singleton 패턴의 장점 

싱글톤 패턴의 장점은 다음과 같다.

 

1. 메모리 절약과 성능향상

 만약 많은 클래스에서 동일한 객체의 인스턴스를 생성해야 하는 경우, 싱글톤 패턴을 적용하지 않았다면 사용할때마다 인스턴스가 생성된다. 물론 어지간해서는 인스턴스를 많이 생성했다고 성능이 저하되는 일은 드물지만 프로젝트의 규모가 크거나 성능이 중요시되는 프로젝트에서는 싱글톤 패턴을 사용하면 큰 도움이 된다.

 

2. 데이터 관리의 측면에서 유리

 하나의 인스턴스만 존재한다는 것은 인스턴스내에 있는 데이터의 관리도 그 곳에서만 하면 된다는 뜻이다. 예를 들어, 어떤 게임에서의 플레이어 점수를 관리하기 위해서는 점수를 관리하는 객체의 인스턴스 내에서 관리를 할 것이다. 싱글톤 패턴을 사용하지 않고 이를 구현하기 위해서는, static 클래스를 생성하거나 생성했던 인스턴스를 계속 유지해야 할것이다. 이는 코드의 품질도 낮출뿐더러 객체지향 프로그래밍 관점에서 바람직한 방법이 아니므로 해당 방법보다는 싱글톤 패턴을 적용하는 것이 바람직하다.

 

Singleton 패턴 구현 방법

일반 클래스에서 싱글톤 패턴 적용

public class SingletonClass
	{
		private static SingletonClass _instance;

		public static SingletonClass Instance
		{
			get
			{
        		// 생성된 인스턴스가 없으면 생성합니다.
				if (_instance == null) 
				{
					_instance = new SingletonClass();
				}
				return _instance;
			}
		}

		public SingletonClass()
		{
			
		}
	}

 

Lazy 싱글톤 적용

 인스턴스의 생성 시기를 선언 즉시 생성이 아니라 인스턴스 내에 있는 값을 접근하려 할 때 생성시켜주는 방법으로 보다 효율적으로 사용할 수 있다. 또한 일반적인 싱글톤에서는 thread-safety를 추가적으로 고려해야 하지만 Lazy 싱글톤을 사용하면 이를 고려하지 않아도 보장된다는 장점이 있다.

(Lazy 싱글톤을 이용한 thread-safety 보장은 인스턴스의 생성에 대한 thread-safety를 보장하는 것이지 이미 생성된 인스턴스의 접근에 대한 보장이 아님.) 

public class SingletonLazy<T> where T : SingletonLazy<T>, new() //제너릭 형식 제약조건(옵션)
	{
		private static Lazy<T> lazyInstance = null;

		public static T Instance
		{
			get
			{
				if (Exists() == false)
				{
					var instance = new T();
					lazyInstance = new Lazy<T>(() => instance);
				}

				return lazyInstance.Value;
			}
		}
		//인스턴스가 만들어졌는지 체크합니다.
		public static bool Exists()
		{
			return lazyInstance != null && lazyInstance.IsValueCreated;
		}
		//인스턴스 생성이력을 초기화 할때 사용합니다.
		public static void ClearInstance()
		{
			lazyInstance = null;
		}
	}

 

유니티 클래스 (MonoBehaviour)에서 싱글톤 패턴 적용

 일반적인 클래스에서 구현하는 싱글톤 패턴과는 달리 C#을 사용하는 유니티의 경우, MonoBehaviour를 상속받는 객체를 싱글톤으로 구현하려는 경우도 종종 있는데 이때는 new 키워드를 통해 인스턴스를 생성할 수 없으므로, 다른 방식으로 구현해야 한다.

public class SingletonClass : MonoBehaviour
{
	private static SingletonClass _instance;

	public static SingletonClass Instance
	{
		get
		{
			// 인스턴스의 값이 null이 아니라면 SingletonClass 오브젝트를 찾아 _instance에 할당합니다.
			if (_instance == null)
			{
				_instance = (SingletonClass)FindObjectOfType(typeof(SingletonClass));
			}
			return _instance;
		}
	}
	// Start is called before the first frame update
	void Start()
	{ 
	}
	// Update is called once per frame
	void Update()
	{
	}
}

 

참조 : https://docs.microsoft.com/ko-kr/dotnet/api/system.lazy-1?view=net-5.0