유니티 버전 - 2022.3.44f1
목차
- 싱글톤 패턴이란?
- 싱글톤 패턴의 역할
- 싱글톤 패턴의 코드 및 설명, 사용법
- 코드 및 설명
- 사용법
- 싱글톤 패턴의 장점과 단점, 코드 개선점
- 장점
- 단점
- 코드 개선점
- 코드 개선하기
- 개선점 1
- 개선점 2
- 개선점 3
- 완성된 코드 및 설명
- 완성코드
- 설명
- 마치며
- 간단 정리
- 참고하면 좋은 자료
싱글톤 패턴이란?
싱글톤 패턴은 특정 클래스의 객체(인스턴스)를 오직 하나만 생성하도록 보장하는 디자인 패턴입니다
주로 게임 상태, 설정, 데이터 관리와 같이 전역적으로 접근해야하는 클래스에서 사용됩니다
인스턴스에 대한 전역적인 접근을 제공하면서도 인스턴스가 여러 개 생성되는 것을 방지 할 수 있습니다
싱글톤 패턴의 코드 및 설명
아래에서 코드에 대하여 설명하겠습니다
using UnityEngine; // Unity의 기본 기능을 사용하기 위한 네임스페이스
public class BasicSingleton : MonoBehaviour // Unity의 기본 기능 사용을 위해 상속받음
{
public static BasicSingleton instance; // 1번 설명
private void Awake() // Start()보다 먼저 1회 실행되는 메서드
{
if(instance == null)
{
instance = this; // 2번 설명
}
else
{
Destroy(gameObject);
}
}
}
1. static 키워드는 프로그램이 시작되면 메모리 내에서 상시 존재 할 수 있도록 해줍니다
1. BasicSingleton은 클래스 자체의 타입을나타내줍니다, 이것은 클래스의 데이터 형식을 의미합니다, 데이터 타입(int, string)처럼 BasicSingleton이라는 클래스를 하나의 타입으로 간주하는 것 입니다
1. instance는 변수의 이름입니다, BasicSingleton의 유일한 객체를 가리키는 역할을 합니다, 다른 스크립트에서 instance를 통해 해당 클래스의 메서드나 변수에 접근할 수 있습니다
2. instance = this; 이 부분은 instance가 null이라면 현재의 인스턴스(this)를 할당하는 것입니다, BasicSingleton 클래스를 대입한다고 생각해도 무방합니다
싱글톤 패턴의 사용법
위와 같이 싱글톤 패턴을 이용하여 클래스를 구현하였다면 해당 인스턴스를 이용해 클래스 외부에서 접근 해보도록 하겠습니다
첫번째로 외부 클래스에서 BasicSingleton클래스의 hp 값을 참조하겠습니다
BasicSingleton 클래스의 hp 값을 참조하여 TestSingleton 클래스의 Debug.Log를 통해 출력해보니 10이 나왔음을 알 수 있었습니다
두번째로 외부 클래스에서 BasicSingleton클래스의 hp 값을 수정하겠습니다
TestSingleton 클래스에서 instance를 이용하여 hp의 값을 1로 수정한뒤 Debug.Log 결과를 보니 1이 출력되는것을 알 수 있었습니다
세번째로 외부 클래스에서 BasicSingleton의 메서드를 이용해보겠습니다
TestSingleton 클래스에서 instance.PrintDebug를 실행한 결과 "singleton" 이 출력되었음을 알 수 있었습니다
싱글톤 패턴의 장점과 단점, 개선점
장점
- 프로그램의 어떤 곳에서든 접근할 수 있습니다, 게임의 상태나 설정 등을 여러 곳에서 쉽게 접근할 수 있습니다
- 외부의 모든 클래스가 동일한 데이터를 사용하게 되므로, 일관된 상태 유지가 가능합니다
단점
- 전역적으로 접근이 가능한 만큼, 어디에서든지 값이 수정될 수 있어 예기치 못한 상태 변화를 초래합니다
- 클래스간의 결합도가 증가하여 코드의 유지보수가 어려워집니다, A의 변경에따라 B의 변경이 강제됩니다
코드 개선점
- 씬이 전환될때 오브젝트가 파괴되어 더 이상 접근 할 수 없게 됩니다
- 싱글톤 패턴을 선언할 때 마다 아래의 작업을 반복해야해서 비효율적입니다
- 외부 클래스에서 instance의 값을 직접 변경할 수 있어서 여러 오류를 일으킬 수 있습니다
코드 개선하기
1. 클래스를 싱글톤으로 바꾸어주는 별도의 클래스를 이용하여 일련의 작업을 간소화 합니다
2. 프로퍼티를 이용하여 외부에서 함부로 instance에 접근하여 수정하는 것을 막아줍니다
3. 씬이 전환될때 오브젝트가 파괴되는 것을 막기 위해 DontDestroyOnLoad() 함수를 사용합니다
완성된 코드 및 설명
using UnityEngine;
public class ConvertToSingleton<T> : MonoBehaviour where T : MonoBehaviour // 1번 설명
{
private static T instance; // 2번 설명
public static T Instance // 2번 설명
{
get
{
return instance;
}
}
protected virtual void Awake()
{
if(instance == null)
{
instance = this as T; // 3번 설명
}
else
{
Destroy(gameObject);
}
}
}
1. ConvertToSingleton<T> 여기서 T는 타입 매개변수로, 데이터의 타입을 동적으로 결정할 수 있게합니다, 어떤 클래스든 싱글톤으로 만들어주기위함입니다, T를 GameManager 클래스로 명시하면 아래의 T들도 GameManager로 치환된다고 생각해도 무방합니다, 이 과정은 자동이기에 신경 쓸 필요가 없습니다
using UnityEngine;
public class GameManager : ConvertToSingleton<GameManager> // GameManager 클래스를 넘겨줌
{
// 외부 클래스 GameManager
}
public class ConvertToSingleton<GameManager> : MonoBehaviour where T : MonoBehaviour
{
private static GameManager instance; // T -> GameManager로 치환
public static GameManager Instance // T -> GameManager로 치환
{
get
{
return instance;
}
}
protected virtual void Awake()
{
if(instance == null)
{
instance = this as GameManager; // T -> GameManager로 치환
}
else
{
Destroy(gameObject);
}
}
}
1. MonoBehaviour where T : MonoBehaviour, 여기서 : MonoBehaviour은 클래스가 MonoBehaviour를 상속받는다는 것을 의미합니다, where T : MonoBehaviour는 제약조건으로서 T가 MonoBehaviour를 상속받는 타입만 허용하도록 해줍니다, 사실상 T에는 클래스만 넘겨줄 수 있다고 생각해도 무방합니다
private static T instance; // 2번 설명
public static T Instance // 2번 설명
{
get
{
return instance;
}
}
2. private statci T instance : instance를 private로 선언해 외부에서 접근할 수 없도록 만들어 수정할 수 없게 합니다
2. public static T Instance : 프로퍼티를 이용하여 외부에서 안전하게 instance에 접근할 수 있도록 해줍니다, 외부에서 싱글톤 패턴이 적용된 클래스에 접근하고 싶다면 클래스명.Instance로 접근할 수 있습니다
protected virtual void Awake()
{
if(instance == null)
{
instance = this as T; // 3번 설명
}
3. 현재 인스턴스(this)를 T 타입으로 캐스팅하고 그 결과를 instance에 할당합니다
this는 현재 인스턴스, 즉 ConvertToSingleton를 상속받은 MonoBehaviour를 가리킵니다, 내가 넘겨준 클래스를 가리킨다고 생각해도 무방합니다
as 연산자는 타입 캐스팅 연산자로써 타입 변화를 시도하고 성공한다면 this를, 실패한다면 null을 반환합니다
여기서 as T는 this(내가 넘겨준 인스턴스인 클래스)를 T(똑같이 내가 넘겨준 클래스) 타입으로 변환하여 인스턴스를 설정하는 것입니다
using UnityEngine;
public class BasicSingleton : ConvertToSingleton<BasicSingleton>
{
protected override void Awake() // 1번 설명
{
base.Awake(); // 2번 설명
DontDestroyOnLoad(gameObject); // 3번 설명
}
}
1. protected override
protected : 해당 클래스 또는 서브클래스에서만 접근할 수 있도록 제한합니다
override : ConvertToSingleton<T>에서 정의된 Awake 를 재정의하여 BasicSingleton 클래스에서 추가적인 초기화 작업을 할 수 있도록 합니다
2. base.Awake()를 통해 ConvertToSingleton의 Awake를 호출합니다
3. DontDestroyOnLoad(gameObject)를 통해 씬 전환시에도 해당 오브젝트가 파괴되지 않도록 해줍니다
마치며
이로써 싱글톤 패턴의 정의와 활용방법, 좀 더 효율적인 코드 사용법을 알아보았습니다
DontDestroyOnLoad(gameObject)가 적용된 오브젝트를 파괴하고 싶을때에는 Destroy(gameObject);를 이용하여 강제로 파괴시킬 수 있습니다
이상입니다
참고하면 좋은자료
https://www.youtube.com/watch?v=Tf_VZEgnag0&ab_channel=UnityKorea
'코드 및 공부 > 디자인 패턴' 카테고리의 다른 글
디자인 패턴 - 싱글톤 패턴(프로퍼티를 이용한 null 체크) (1) | 2024.10.22 |
---|