본문 바로가기

Design Pattern

[Design Pattern] 19. Singleton Pattern(싱글톤 패턴) C#

728x90

클래스에 인스턴스가 하나만 있도록 하면서 전역 접근을 도와주는 디자인 패턴입니다.

 

생성 패턴(Creational Design Patterns) 중 하나입니다.

 

장점

  • 클래스가 하나의 인스턴트만 갖습니다.
  • 전역에서 동일한 객체 접근이 가능합니다.
  • 처음에만 초기화 됩니다..

단점

  • 단일 책임 원칙을 위반하여 한 번에 여러 문제를 동시에 해결합니다.
  • 코드가 꼬일 수 있습니다.
  • Thread-Safety하지 않을 수 있습니다.
  • 유닛 테스트 하기 힘듭니다.

 

C#으로 Console 프로젝트를 하나 생성해서 할 것입니다.

이번엔 생성 패턴에 싱글톤이라 뭐가 많이 없습니다.

 

일단 프로젝트의 tree구조는 아래와 같습니다.

Singleton (Project)

|- Program.cs (Main)

|- Singleton.cs (Singleton Class)

 

그럼 구현해 보겠습니다.

Singleton.cs

using System;

namespace Singleton
{
    public sealed class Singleton
    {
        public string _context { get; set; } = "init";
        private static readonly Lazy<Singleton> instanceHolder = new Lazy<Singleton>(() => new Singleton());

        private Singleton() { }

        public static Singleton GetSingleton()
        {
            return instanceHolder.Value;
        }

    }

}

여기서 핵심은 private으로 되어있는 생성자이며 class도 sealed로 상속을 막아 놨습니다.

 

Lazy<Singleton>으로 만들고 Get을 할시 Lazy객체에서 Value를 리턴해 줍니다.

Lazy를 쓰는 이유는 호출 시점에 객체가 생성됨을 보장을 받기 때문입니다.

이로써 Thread-Safety하게 됩니다.

사용할 내용인 _context도 string으로 하나 만들어 줍니다.

 

Program.cs

using System;

namespace Singleton
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(GetContext());
            SetContext("change context");
            Console.WriteLine(GetContext());
        }

        static void SetContext(string context)
        {
            Singleton.GetSingleton()._context = context;
        }

        static string GetContext()
        {
            return Singleton.GetSingleton()._context;
        }
    }
}

Get,Set Context를 만들어 둘이 사용하는 context를 Singleton에서 Get해서 만들어 줍니다.

그리고 Set하고 다시 Get한 시점에 Set한 값으로 나오면 둘이 같은 객체를 사용함을 확인할 수 있을 것입니다.

 

처음 Default값인 "init"이 나오고 다음에 바꿔 준 뒤 다시 가져왔을 때 바뀌었음을 확인 할 수 있습니다.

실행 결과

하나의 객체임이 보존되기 때문에 Log 찍을 때 Logger를 만들거나 아니면 리소스를 많이 쓸 법한 객체에 사용 합니다.

제가 아는 어느 분은 싱글톤을 static쓰기 양심에 찔릴 때 쓴다고 말했습니다.

 

Lazy로 만들었지만 그냥 private인 생성자에 static으로 객체를 하나만 가지고 있어도 싱글톤이라고 할 수 있습니다.