Deff_Dev
[디자인 패턴] 싱글톤 패턴 (Singleton Pattern) 본문
싱글톤 패턴이란 ?
- 게임 상이나 메모리 상으로 단 하나만 존재하며 언제 어디서든 사용 가능한 오브젝트를 만들 때 사용된다.
- 유니티에서는 오디오 관리, 데이터 관리, 설정 관리 등등 게임 내에서 전반적으로 사용, 관리되어야 할 때 싱글톤 패턴을 사용하면 유용하다.
싱글톤 패턴 특징
- 접근성 : 스크립트의 접근성이 높아진다.
- 유일성 : 기능 별로 단 하나만 유일하게 존재해야한다.
기본적인 사용법
using UnityEngine;
public class GameManager : MonoBehaviour
{
// static으로 선언해 해당 인스턴스를 접근 가능하게 함
public static GameManager instance = null;
private void Awake()
{
if (instance == null) // instance가 null이라면
{
instance = this; // instance에 자기 자신을 저장함
DontDestroyOnLoad(this.gameObject); // 씬이 넘어가도 해당 오브젝트가 사라지지 않게함
}
else
{
Destroy(this.gameObject); // 이미 인스턴스를 생성했다면 Destroy
}
}
}
싱글톤 패턴 단점
- static을 사용하여 선언하기 때문에 게임을 종료할 때까지 메모리를 점유하므로 메모리 누수가 발생할 수 있다.
- 싱글톤은 전역 상태를 유지하므로 코드의 복잡성을 증가시킬 수 있고 유지보수가 힘들어 질 수도 있다.
→ 편리하다고 많이 사용하면 치명적인 오류가 발생할 수 있으니 꼭 필요한 기능만 최소화해서 사용해야 한다.
위의 코드처럼 싱글톤 객체를 생성하는 방식은 매 스크립트마다 중복해서 선언해야 하므로 비효율적이다.
그래서 제네릭을 이용하여 싱글톤 클래스를 만들고 해당 클래스를 상속하는 방식으로 효율적으로 싱글톤 객체를 생성할 수 있다.
제네릭을 이용한 싱글톤 생성 예
using UnityEngine;
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T instance;
public static T Instance
{
get
{
if(instance == null)
{
// 해당 컴포넌트를 가지고 있는 게임 오브젝트를 찾아서 반환한다.
instance = (T)FindAnyObjectByType(typeof(T));
if (instance == null) // 인스턴스를 찾지 못한 경우
{
// 새로운 게임 오브젝트를 생성하여 해당 컴포넌트를 추가한다.
GameObject obj = new GameObject(typeof(T).Name, typeof(T));
// 생성된 게임 오브젝트에서 해당 컴포넌트를 instance에 저장한다.
instance = obj.GetComponent<T>();
}
}
return instance;
}
}
private void Awake()
{
if(transform.parent != null && transform.root != null) // 해당 오브젝트가 자식 오브젝트라면
{
DontDestroyOnLoad(this.transform.root.gameObject); // 부모 오브젝트를 DontDestroyOnLoad 처리
}
else
{
DontDestroyOnLoad(this.gameObject); // 해당 오브젝트가 최 상위 오브젝트라면 자신을 DontDestroyOnLoad 처리
}
}
}
using UnityEngine;
// Singleton 클래스를 상속하면 쉽게 인스턴스를 생성할 수 있다.
public class GameManager : Singleton<GameManager>
{
public void GameStart()
{
Debug.Log("게임 시작");
}
}
하나의 싱글톤 인스턴스에 너무 많은 기능과 데이터를 넣으면 객체지향 설계 원칙인 SRP(Single Responsibility Principle)와 OCP(Open-Closed Principle)를 어길 수 있고, 이는 유지보수에 치명적일 수 있다.
따라서 싱글톤을 사용할 때에는 해당 인스턴스의 의존도를 낮추고, 한 가지 역할만 수행하도록 설계해야한다.
객체지향 설계 원칙(SOLID)
단일 책임의 원칙 (SRP) (Single Responsibility Principle) |
하나의 클래스는 하나의 목적을 위해 생성한다는 원칙 |
개방 폐쇄 원칙 (OCP) (Open Close Principle) |
소프트웨어의 구성요소는 확장에는 열려있고, 변경에는 닫혀있어야 한다는 원칙 |
리스코프 치환의 원칙 (LSP) (Liskov Subsitution) |
서브 타입(상속받은 하위 클래스)은 어디서나 자신의 기반 타입(상위 클래스)으로 교체할 수 있어야 한다는 원칙 |
인터페이스 분리의 원칙 (ISP) (Interface Segregation Principle) |
클라이언트는 자신이 사용하지 않는 메서드와 의존관계를 맺으면 안되고, 클라이언트가 사용하지 않는 인터페이스 때문에 영향을 받아서는 안된다는 원칙 |
의존성 역전의 원칙 (DIP) (Dependency Inversion Principle) |
실제 사용 관계는 바뀌지 않으며, 추상을 매개로 메시지를 주고받음으로써 관계를 최대한 느슨하게 만드는 원칙 |
참고자료
https://www.youtube.com/watch?v=a5TCCQgdv-E&t=622s
스스로 공부하면서 정리한 내용으로 틀린 내용이 있을 수도 있습니다. 고쳐야할 점이 있다면 댓글 달아주세요 !
'CS > 디자인 패턴' 카테고리의 다른 글
[디자인 패턴] 프로토타입 패턴 (Prototype Pattern) (0) | 2024.11.08 |
---|---|
[디자인 패턴] 옵저버(관찰자) 패턴 (Observer Pattern) (0) | 2024.11.07 |
[디자인 패턴] 경량 패턴 (Flyweight Pattern) (0) | 2024.11.07 |
[디자인 패턴] 명령 패턴 (Command Pattern) (1) | 2024.11.07 |
[디자인 패턴] 디자인 패턴 (서비스 로케이터, 데코레이터, 빌더/팩토리, 상태) (0) | 2024.06.04 |