logo MSJO.kr

Singleton Design Pattern in C#

2019-08-26
MsJ

디자인 패턴은 소프트웨어 디자인 및 아키텍처의 중용한 부분이다. 디자인 패턴이란 ‘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();
        }
    }
}
// Generics
using System;
using System.Threading.Tasks;

namespace ConsoleExam
{
    internal class Program
    {
        private static async Task Main()
        {
            Console.WriteLine(await Singleton<Hello>.Go.PrintMessage("가가가 - ") + Singleton<Hello>.Go.Time + "s");

            Singleton<Hello>.Go.Name = "World";
            Console.WriteLine(await Singleton<Hello>.Go.PrintMessage("나나나 - ") + Singleton<Hello>.Go.Time + "s");

            var instance = Singleton<Hello>.Go;
            instance.Name = "Total";
            instance.Time = 3;
            Console.WriteLine(await instance.PrintMessage("닭닭닭 - ") + instance.Time + "s");
        }
    }

    public class Singleton<T> where T : class, new()
    {
        private Singleton() { }

        private static readonly Lazy<T> instance = new(() => new T());

        public static T Go { get { return instance.Value; } }
    }

    public class Hello
    {
        private static int counter = 0;

        public string Name { get; set; }
        public double Time { get; set; }

        public Hello()
        {
            Name = "Hello";
            Time = 1;
            counter++;
            Console.WriteLine("Counter : " + counter.ToString());
        }

        public async Task<string> PrintMessage(string message)
        {
            var str = Name + " : " + message;
            await Task.Delay(TimeSpan.FromSeconds(Time));
            return str;
        }
    }
}

Prεv(Θld)   Nεxt(Nεw)
Content RustLang.kr
Search     RSS Feed     BY-NC-ND