ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 닷넷 3.5를 이용한 디자인 패턴의 구현 (8)
    DesignPatterns 2009. 8. 19. 00:16
    반응형

    Singleton 패턴

    아마도 가장 유용하다고 가장 단순한 디자인 패턴 중의 하나가 Singleton 패턴이다. 이 패턴의 목적은 프로그램의 실행 시간 동안에 한 오브젝트의 인스턴스가 만들어졌는지 확인하는 것이다.

    Singleton 패턴의 일반적인 구현은 다른 클래스들이 접근할 수 없는 private 생성자와  public 메소드를 만드는 것이다. 이때, 메소드는 자신이 호출될 때 존재하는 인스턴스가 없으면 만들고, 있다면 기존의 인스턴스가 가지고 있던 작업을 가지고 있는 생성자와 비슷한 영할을 한다.

    Singleton과 멀티스레딩
    Singleton 패턴의 구현은 멀티스레딩 프로그램에서 약간의 트릭을 얻을 수 있다. 그래서, 프로그래머들은 Singleton 패턴을 다시 구현하기보다는 잘 테스트된 코드를 종종 사용한다. 두개의 스레드가 싱글톤이 아직 존재하지 않는 상활에서 동시에 생성 메소드를 실행시킨다면, 이들은 서로 싱글톤의 인스턴스가 있는지 체크해야 한다. 그리고, 한쪽에서만 새로운 인스턴스를 만들어 내야 한다. 또한, 프로그래밍 언어가 닷넷의 언어들처럼 동시 처리기능을 가지고 있다면, 메소드는 상호 배타적으로 실행되도록 구성되어야 한다.

    이러한 문제의 고전적인 해법은 오브젝트가 인스턴스화되고 있는 중이라는 것을 알려주는 클래스에서 뮤텍스(mutext)나 다른 스레드 잠금 로직을 통해 상호 배제(mutual exclusion)를 사용하는 것이다 .Singleton패턴은  Factory Method패턴과 함께 시스템 전체에서 사용하는 특정 타입을 가진 리소스를 만들기 위해 자주 사용된다. 이 리소스를 사용하는 코드에서는 타입을 알지 못한다.


    Singleton 패턴을 표현한UML 클래스 다이어그램

    예제로 알아보는 Singleton 패턴

    Singleton 패턴을 알아보기 위해서, 새로운 콘솔 응용프로그램을 만들고 SMTPHost라는 단순한 오브젝트를 추가한다.

      // 간단한 서버 프로그램
        class SMTPHost
        {
            private string name;
            private string ip;

            public SMTPHost(string name, string ip)
            {
                this.name = name;
                this.ip = ip;
            }

            public string Name
            {
                get { return name; }
            }
            public string IP
            {
                get { return ip; }
            }
        }

    값을 할당할 수 있는 방법이 없기 때문에 프로퍼티의 값을 받아들일 변수를 만들어 주어야 한다.

    이제, SMTPHost 오브젝트들의 리스트(smtpServers)를 가지고 있는 MailDelievry 클래스를 만든다. MailDelivevry 생성자에서 10개의 SMTPHost 오브젝트를 만든다

      private MailDelivery()
            {
                // 이용할 수 있는 smtp 서버의 목록
                smtpServers.Add(new SMTPHost("Mail 1 ", "192.168.0.100"));
                smtpServers.Add(new SMTPHost("Mail 2 ", "192.168.0.101"));
                smtpServers.Add(new SMTPHost("Mail 3 ", "192.168.0.102"));
                smtpServers.Add(new SMTPHost("Mail 4 ", "192.168.0.103"));
                smtpServers.Add(new SMTPHost("Mail 5 ", "192.168.0.104"));
                smtpServers.Add(new SMTPHost("Mail 6 ", "192.168.0.104"));
                smtpServers.Add(new SMTPHost("Mail 7 ", "192.168.0.110"));
                smtpServers.Add(new SMTPHost("Mail 9 ", "192.168.0.120"));
                smtpServers.Add(new SMTPHost("Mail 10 ", "192.168.0.150"));
            }



    주의할 점은 생성자가 private라는 점이다. 이전에 언급했듯이, 이것은 이 프로그램이 단지 MailDelivery 오브젝트의 인스턴스가 없거나 하나만 가져야 하기 때문이다. 클라이언트들이 MailDelivery 오브젝트를 요청할 때, 이 오브젝트는 싱글톤이 될것이다. 예제에서는 SMTPServer프로퍼티를 호출하면 , MailDelivery의 SMTPServer 오브젝트들의 목록중에서 임의의 하나를 반환하는 로드 밸런싱을 흉내 낸다.

    public SMTPHost smtpServer
            {
                get
                {
                    int r = random.Next(smtpServers.Count);
                    return smtpServers[r];
                }
            }

    MailDelivery를 정적(static)인스턴스로 선언할 때 스레드 문제를 조심하자. 다행히, 닷넷은 이러한 경우에 스레드 안정성을 보증한다

    이 프로그램이 실행되는 과정에서 출력되는 결과를 보여준다


    이 장의 예제이다

    디자인패턴의 놀라운 세계에 들어갈 준비가 되었다


    - 참고  Programming .Net 3.5 by Jesse Liberty and Alex Horovitz.
    반응형

    댓글

Designed by Tistory.