singleton design pattern in c#

디자인 패턴은 소프트웨어 디자인 및 아키텍처의 중용한 부분이다. 디자인 패턴이란 ‘Creational Design Patterns’, ‘Structural Design Patterns’, ‘Behavioral Design Patterns’와 같이 3가지 유형으로 나누어 볼 수 있다(C-SharpCorner 2013). 애플리케이션이 시작될 때 어떤 클래스가 최초 한 번만 메모리를 할당하고(Static) 그 메모리에 인스턴스를 만들어 사용하는 디자인 패턴(JEONG_AMATEUR 2017)인 ‘Singleton Design Pattern’에 대해 간략하게 정리하였다. Singleton과 Static 함수의 차이점은 Singleton인 경우 멤머 변수 등을 가지며 생성자/소멸자에서 뭔가를 해야 할 경우 그리고 Static 함수로 구성하는 경우는 멤버 변수 및 this 포인트를 쓸 필요 없으며 생성자/소멸자에서 뭔가 할 필요가 없을 때(KLDP 2013) 이다.

Singleton 패턴의 장단점에 대해서는 ‘Singleton Design Pattern In C#’ 글을 참고하자.

  • What is Singleton Design Pattern?
  • Advantages of Singleton Pattern
  • Disadvantages of Singleton Pattern
  • Singleton class vs. Static methods
  • How to Implement Singleton Pattern in your code

아래의 소스(콘솔예제)는 기본적인 사용법과 스레드(thread)에 안정적인 사용법을 보여준다.

Default singleton
using System;

namespace SingletonDemo
{
    public sealed class SingletonDefault
    {
        private static int counter = 0;
        private static SingletonDefault instance = null;

        public static SingletonDefault GetInstance
        {
            get
            {
                if (instance == null)
                    instance = new SingletonDefault();
                return instance;
            }
        }

        private SingletonDefault()
        {
            counter++;
            Console.WriteLine("Counter Value D : " + counter.ToString());
        }

        public void PrintMessage(string message)
        {
            Console.WriteLine(message);
        }
    }
}
Lazy singleton (thread)
using System;

namespace SingletonDemo
{
    public sealed class SingletonLazy
    {
        private static int counter = 0;
        private static readonly Lazy<SingletonLazy> instance = new Lazy<SingletonLazy>(() => new SingletonLazy());

        public static SingletonLazy GetInstance
        {
            get
            {
                return instance.Value;
            }
        }

        private SingletonLazy()
        {
            counter++;
            Console.WriteLine("Counter Value S : " + counter.ToString());
        }

        public void PrintMessage(string message)
        {
            Console.WriteLine(message);
        }
    }
}
사용예
using System;

namespace SingletonDemo
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            if (args == null || args.Length == 0)
            {
                Console.WriteLine("Code when no arguments are supplied");
            }
            else
            {
                Console.WriteLine("Code when arguments are supplied");
            }

            Console.WriteLine("-----------------------------");

            SingletonDefault D1 = SingletonDefault.GetInstance;
            D1.PrintMessage("D1 messageD1");

            SingletonDefault D2 = SingletonDefault.GetInstance;
            D2.PrintMessage("D2 messageD2");

            Console.WriteLine("-----------------------------");

            SingletonLazy S1 = SingletonLazy.GetInstance;
            S1.PrintMessage("S1 messageS1");

            SingletonLazy S2 = SingletonLazy.GetInstance;
            S2.PrintMessage("S2 messageS2");

            SingletonLazy.GetInstance.PrintMessage(Environment.NewLine + "Test...End...");

            Console.ReadLine();
        }
    }
}