공부일지

싱글톤 패턴(작성중) 본문

독서/게임 프로그래밍 패턴

싱글톤 패턴(작성중)

이하택 2023. 9. 27. 05:10
1️⃣

들어가며

본 서적의 화자는 ‘싱글턴 패턴은 득보다는 실이 많다.’ 라고 언급하며

다른 패턴들과는 별개로 어떻게 하면 싱글턴 패턴을 지양하는가를 서술한다.

싱글턴 패턴에 대하여

  • 오직 한개의 클래스 인스턴스만 갖도록 보장
  • 인스턴스가 여러 개라면?

    = 외부 시스템과 상호작용하며 전역상태 관리하는 클래스

    • ex) 파일 시스템 API 래핑 시스템
      • 파일 작업 완료 시간을 고려하여 클래스는 비동기로 동작

        = 여러 작업이 동시에 진행될 수 있음.

      • 한쪽에선 파일 생성, 한쪽에선 방금 생성한 파일 삭제 등등
    • 래퍼 클래스가 두 작업을 파악해서 조율해야함.

→ 클래스로 들어온 호출이 이전 작업 전체에 접근할 수 있어야함.

  • 아무데서나 인스턴스를 만들 수 있다면 다른 인스턴스의 작업에 접근 불가.

→ 싱글턴으로 만들면 클래스가 인스턴스를 하나만 가지므로 컴파일 단계에서 강제

  • 전역 접근점을 제공
    • 호출하고자 하는 시스템에서 파일 시스템 클래스 인스턴스를 생성할 수 없다면?

      =하나의 인스턴스 생성 + 전역 접근

  • 예제 코드
    일단 생략

왜 사용하는가

  • 장점들
    • 한 번도 사용하지 않는다면 아예 인스턴스를 생성하지 않는다.
      • 처음 사용될 때 초기화되므로
      • 이건 유니티에서도 동일한가?
        • 가령 오브젝트로 꺼내놓은 사운드 매니저 등은?
    • 런타임에 초기화된다.
      • 보통 싱글턴 대안으로 정적 멤버 변수를 많이 사용한다.
      • 그러나 컴파일러는 main 함수를 호출하기 전에 정적 변수를 초기화 하기에 프로그램 실행 뒤에 알게되는 정보를 활용할 수 없다.
      • 싱글턴은 최대한 늦게 초기화됨( : 게으른 초기화 )
    • 싱글턴을 상속할 수 있다 (싱글턴 오버라이드)
      • ex) 특정 시스템 클래스가 Switch, Ps5, Steam등의 크로스 플랫폼을 지원한다 가정
      • 파일 시스템 래퍼로 추상 인터페이스를 만든 뒤, 플랫폼마다 구체 클래스를 만들면 됨.
      • 코드
        private enum Platform
        {
        	PS5,
        	Switch
        }
        public class FileSystem : MonoBehaviour
        {
        	public static FileSystem instance;
        	private Platform _platform;
        
        	void Awake()
        	{
        		if(_platform == PS5)
        			instance = new PS5FileSystem();
        		else if(_platform == Switch)
        			instance = new SwitchFileSystem()
        		else
        			instance = this;
        	}
        
        	virtual FileSystem() {}
        	virtual string readFile(string path) {}
        	virtual void writeFile(string path, string contents) {};
        }

        →상위 클래스

        →추가로 포인터변수(char*)를 C#에서 대체하기 어렵기에 string으로 뭉개버려서 문제가 발생할 지도

        public class PS5FileSystem : FileSystem
        {
        	override string readFile(string path)
        	{
        		//소니의 파일 IO API 사용
        	}
        	override void writeFile(string path, string contents)
        	{
        		//소니의 파일 IO API 사용
        	}
        }
        ~~~

        →하위 클래스

무엇이 문제인가

  • 알고보니 전역변수
    • 코드 이해하기 힘들어
    • 커플링 조장
    • 동시성 프로그래밍에 알맞지 않다.(멀티스레딩 등)
  • 문제가 하나 뿐일 때에도 두 가지 문제를 풀려 든다.
  • 게으른 초기화는 제어할 수가 없다.

대안책

  • 클래스가 꼭 필요한가?
  • 오직 한 개의 클래스 인스턴스만 갖도록 보장하기
  • 인스턴스에 쉽게 접근하기
    • 넘겨주기
    • 상위 클래스로부터 얻기
    • 전역인 객체로부터 얻기
    • 서비스 중개자로부터 얻기

정말로 싱글턴을 사용해야하는 시점


Uploaded by N2T