C# & VB.NET2007. 2. 12. 15:33

현재, 몸담고 있는 회사의 솔루션 코드를 보다가 이런 것을 발견했다.

Imports System.Threading

Public Class Metadata
    Private myMetadata As New InsightMetadata

    Private Shared _singleton As Metadata
    Private Shared myInstanceMutex As New Mutex


    Private Sub New()
    End Sub

    Public Shared Function GetInstance() As Metadata

        myInstanceMutex.WaitOne()

        Try
            If _singleton Is Nothing Then
                _singleton = New Metadata
            End If

        Finally
            myInstanceMutex.ReleaseMutex()
        End Try

        Return _singleton

    End Function

    Public ReadOnly Property Appset(ByVal appsetID As String, ByVal app As String, ByVal userName As String, ByVal context As String, ByVal security As String) As Appset
        Get
            If (IsNothing(myMetadata.Appset(appsetID))) Then
                load(appsetID, app, userName, context, security)
            End If

            Return myMetadata.Appset(appsetID)
        End Get
    End Property

    Public Overloads Sub refresh(ByVal appset As String, ByVal app As String, ByVal userName As String, ByVal context As String, ByVal security As String)
        load(appset, app, userName, context, security)
    End Sub

    Private Function load(ByVal appsetID As String, ByVal app As String, ByVal userName As String, ByVal context As String, ByVal security As String) As Appset
        ...
    End Function
End Class

이 코드는 클래스 이름으로도 대충 짐작이 가듯이 전체 프로그램의 공용 Meta 데이터들을 저장해 놓는 모듈이다. 이런 메타 데이터들은 많은 모듈에서 사용하면서도 프로그램이 구동 중일 때는 거의 바뀌지 않는다는 속성이 있다. 그래서 이런 메타데이터는 메모리에 하나 올려놓고, 그것을 모두 사용하면 가장 좋을 것이다. 매번 읽어오지도 않고, 각 모듈에서 각각 호출하지도 않게 하는 최선의 방법일테니까 말이다.

싱글턴 패턴

이렇게 메모리에 딱 하나의 인스턴스를 올려놓을 필요가 있을 때 쓰는 것이 바로 "Singleton" 패턴이다. "Design Patterns"에 나오는 정의를 보자면 "ensure a class has only one instance, and provide a global point of access to it""한 클래스가 단지 하나의 인스턴스만을 가지게 하고, 그것에 액세스할 수 있는 글로벌한 포인트를 제공하는 것"이라고 되어 있다. 아래 위키 백과 페이지를 참조하면 더 자세하게 알 수 있다.

싱글턴 패턴 - 위키 백과

싱글턴 쓰임새

싱글턴 패턴은 쓰임새가 그렇게 다양하진 않다. 주로 위의 코드와 같은 메타 데이터, 혹은 파일 로깅 등의 공용 모듈에서 사용된다. (물론 위의 조건 - 하나의 인스턴스, 글로벌한 액세스 - 을 충족시킨다면 그 쓰임새 자체는 제한이 없다) 하지만 아래 글에서 볼 수 있듯이 이 Singleton 클래스는 다른 클래스들과 단단하게 결합되는(tightly-coupled) 경향이 있고, 이는 Unit Test를 어렵게 하고 전체적으로 각 모듈의 독립성을 저해하는 요소로 작용할 수도 있다. 아래와 같은 글들을 참고할 만 하다. (물론 주의깊게 읽어야 할 것이다. 단지 주장일 뿐이니)

IBM Developerworks: Use Your Singleton Wisely
PrestonLee.com: Singletons causes cancer

권장하는 닷넷 코드

MSDN: Exploring the Singleton Design Pattern

Implementing the Singleton Pattern in C#

MSDN의 Article도 괜찮긴 하지만, 2번째 글은 그야말로 총정리다. C#에서 가능한 모든 경우의 Singleton 구현에 대해서 모두 그 장단점을 서술해놓고 있다. 2번째 글을 보면 이 글의 처음에 나온 코드는 (MSDN 글을 봐도 그렇다) 그다지 좋지 못한 예라는 것을 알 수 있다..^^ 그래서 나도 현재 코드를 바꾸고 있는 중이다. 2번째 글의 네번째 버전으로(아래와 같이) 바꿀 예정이다. MSDN Article에 있는 코드와도 거의 같다고 보면 된다.

public sealed class Singleton
{
static readonly Singleton instance=new Singleton();

// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Singleton()
{
}

Singleton()
{
}

public static Singleton Instance
{
get
{
return instance;
}
}
}

Posted by kkongchi