관련 영상
싱글턴 패턴
위키피디아-싱글턴 패턴
설명 및 스도코드
- 싱글턴 패턴(Singleton pattern)을 따르는 클래스는, 생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고 최초 생성 이후에 호출된 생성자는 최초의 생성자가 생성한 객체를 리턴한다.
싱글턴의 구조
- 싱글턴 클래스
- 정적 메서드
getInstance
를 선언, 이 메서드는 자체 클래스의 동일한 인스턴스 반환
- 싱글턴의 생성자는 항상 클라이언트 코드에서부터 숨겨져야 함
싱글턴의 문제점
- 클래스에 인스턴스가 하나만 있도록 한다.
- 클래스에 있는 인스턴스 수를 제어하려는 가장 일반적인 이유는 일부 공유 리소스에 대한 접근을 제어하기 위함
- 객체를 생성했지만 잠시 후 새 객체를 생성하기로 했다고 가정했을 때, 새 객체를 생성하는 대신 이미 만든 객체를 받게 된다. 물론 생성자 호출은 특성상 반드시 새 객체를 반환해야 하므로 위 행동은 일반 생성자로 구현할 수 없다.
- 해당 인스턴스에 대한 전역 접근 지점을 제공
- 필수 객체들을 저장하기 위해 전역 변수들을 정의했을 때 이 변수들을 사용하면 매우 편리할지는 몰라도, 모든 코드가 잠재적으로 해당 변수의 내용을 덮어쓸 수 있고 그로 인해 앱에 오류가 발생해 충돌할 수 있으므로 그리 안전한 방법은 아니다.
- 싱글턴 패턴은 스파게티 코드를 만들어 유닛 테스트를 어렵게 할 가능성이 높게 된다
싱글턴 패턴의 적용
- 싱글턴 패턴은 프로그램의 클래스에 모든 클라이언트가 사용할 수 있는 단일 인스턴스만 있어야 할 떄 사용
- 싱글턴 패턴은 특별 생성 메서드를 제외하고 클래스의 객체들을 생성할 수 있는 모든 다른 수단들을 비활성화 한다.
- 전역 변수들을 더 엄격하게 제어해야 할 때 사용
- 전역 변수들과 달리 싱글턴 패턴은 클래스의 인스턴스가 하나만 있도록 보장해준다
- 싱글턴 패턴은 단일 책임 원칙을 엄격히 따라 싱글턴 클래스의 비대화를 방지한다
다른 패턴과의 관계
- 퍼사드 패턴의 클래스는 종종 싱글턴으로 변환될 수 있음
- 객체들의 공유된 상태를 단 하나의 플라이웨이트 객체로 즐일 수 있으면 플라이웨이트는 싱글턴과 유사해질 수 있음 그러나 둘에게는 두 가지의 근본적인 차이점이 존재
- 싱글턴은 인스턴스가 하나만 있어야 하지만 플라이웨이트는 여러 고유한 상태를 가진 여러 인스턴스를 포함할 수 있음
- 싱글턴 객체는 변할 수 있지만 플라이웨이트 객체들은 변할 수 없음
- 추상 팩토리들, 빌더들, 프로토타입들은 모두 싱글턴으로 구현 가능
유니티에서의 싱글턴 패턴
MonoBehaviour
을 상속받아 디폴트 생성자를 막음으로써 싱글턴의 문제점 1번을 해결한다
class Singleton : MonoBehaviour
{
public static Singleton Instance { get; private set; }
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(this.gameObject);
}
else
{
Instance = this;
}
}
}
유니티 싱글턴 오디오 매니저
- 참고 영상
- 오디오 매니저
- 배경음 혹은 효과음을 출력해주는 오디오 매니저는 하나의 게임 클라이언트에 하나만 필요하므로 싱글턴으로 구현할 수 있다.
- 해당 코드에서는
setter
를 private
으로 하여 외부의 임의적인 값 변경을 차단하였다
/* 오디오 매니저 */
public class AudioManager : MonoBehaviour
{
public static AudioManager Instance { get; private set; }
private void Awake()
{
Instance = this;
_audioSource = GetComponent<AudioSource>();
}
private Queue<AudioSource> _audioSources = new Queue<AudioSources>();
private AudioSource _audioSource;
public void PlayClipAtPoint(AudioClip clip, Vector3 point)
{
// 소리와 소리나는 방향을 이용해 소리 구현
}
// 활성화되면 자식 오브젝트에 오디오 소스 컴포넌트를 생성한 후 큐에 저장
private void OnEnable()
{
if (transform.childCount > 0)
return;
for (int i = 0; i < 10; i++)
{
var audioSourceGameObject = new GameObject("AudioSource " + i);
audioSourceGameObject.transform.SetParent(transform);
var audioSource = AudioSourceGameObject.AddComponent<AudioSource>();
_audioSources.Enqueue(audioSources);
}
}
}
유니티 제네릭 싱글턴 클래스
Monobehaviour
를 상속하는 클래스들을 싱글턴으로 만들어주는 제네릭 클래스이다.
- 이런게 있다 정도만 알면 충분
public class LazeInstantiatedSingleton<T> : MonoBehaviour
where T : MonoBehaviour
{
private static T _instance;
public static T Instance
{
get
{
if (_instance == null)
{
_instance = GameObject.FindObjectOfType<T>();
if (_instance == null
{
_instance = new Gameobject().AddComponent<T>();
}
}
return _instance;
}
}
}