본문 바로가기
c#

[c#] static과 singleton사용예제

by devjh 2020. 7. 7.
반응형

static의 사용예제에 대해 알아보겠습니다.

 

c#을 처음 공부할때 static은 한번 선언되면 다시 선언할수 없다. 라는 특징으로 접근했던 기억이 있습니다.

 

사실 static 예약어는 클래스 내부에 정적필드를 만들때 주로 사용합니다.(전역화시킨다고도 합니다.)

 

1. 예제

namespace StaticTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Person person1 = new Person("Tom");
            Console.WriteLine(person1.personCount);

            Person person2 = new Person("John");
            Console.WriteLine(person2.personCount);

        }
    }

    class Person
    {
        public int personCount;
        public string name;

        public Person(string name)
        {
            this.name = name;
            personCount++;
        }
    }
}

 

저는 personCount로 Person객체가 몇개 생성됐나를 파악하고 싶었으나

 

출력값은 1과 1입니다.(각각의 멤버변수이므로)

 

 

2. static 예약어 사용

namespace StaticTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Person person1 = new Person("Tom");
            Console.WriteLine(Person.personCount);

            Person person2 = new Person("John");
            Console.WriteLine(Person.personCount);

        }
    }

    class Person
    {
        // static 예약어로 정적 필드로 만든다.
        static public int personCount;
        public string name;

        public Person(string name)
        {
            this.name = name;
            personCount++;
        }
    }
}

이제 Person클래스의 객체가 생성될때마다 personCount가 증가합니다.

 

여기서 주의할 점은 정적멤버는 객체에서 접근하는것이 아니라 '클래스이름.정적필드' 로 접근합니다.

 

static키워드와 함께 선언된 personCount 변수는 마치 전역변수처럼 활용이 가능합니다.

 

또한 메서드 앞에도 static을 붙여 메서드도 정적메서드로 만들 수 있습니다.

 

단 정적메서드에서는 정적필드에만 접근이 가능합니다(멤버변수에는 접근하지 못합니다.)

 

왜 정적메서드에서는 멤버변수에 접근을 못하나 생각해보면

 

정적메서드는 클래스명.정적메서드로 불러오기에 일단 어떤객체의 멤버변수에 접근할지 모르며

 

클래스변수들은 new로 생성해서 힙할당을 하는 반면

 

정적변수, 정적메서드들은 따로 힙에 할당이 되지 않습니다.

 

라이브러리에 포함된 간단한 static의 예를 들자면

 

그동안 Console.WriteLine를 아무생각 없이 사용했지만 Console이라는 클래스의 WriteLine이라는 static 메서드를 호출 한 것입니다.

 

 

 

3. singleton 구현

Class Person
{
    static public Person onlyOnePerson = new Person("홍길동");
    string name;
    
    private Person(string name)
    {
    	this.name = name;
    }
    
    public getName()
    {
    	Console.WriteLine(name);
    }
}

private생성자가 등장하였습니다.

 

이제 외부에서는 이친구를 생성하지 못합니다.

 

그리고 static예약어를 사용해 onlyOnePerson으로 객체를 하나 만들어놨습니다.

 

즉 이 클래스는 단 하나의 객체만 보유하고있으며 더이상 생성할 수 없습니다.

 

접근방법은 이렇습니다.

 

Person.onlyOnePerson.getName();

 

이렇게 인스턴스가 단 하나만 존재하는 타입을 singleton 클래스라고 하며

 

시스템 내부의 자원을 공유하는 기능의 클래스가 필요할때 싱글턴클래스를 만들어 자원을 공유하곤 합니다.

 

 

 

위의 방법은 싱글턴의 기본 개념을 정리한 것이며

 

실제로 싱글턴 패턴은 이렇게 사용 하는 경우가 많습니다.

 

4. 조금더 우아하게 singleton 구현2

class Share
{
    private static Share instance=null;

    private Share()
    {
    
    }

    public static Share getInstance
    {
        get
        {
             if (instance == null)
             {
                 instance = new Share();
             }
             return instance;
        }
    }
}

 

멀티스레딩 환경에서는 getinstance내부 전체를 lock으로 묶어 thread safety하게 구현해줘야합니다.

 

이제 Share클래스안에 시스템 자원을 넣어주고

 

아래 구문과 함께라면 어디서든 이 객체에 접근해서 자원을 꺼내 쓸 수 있습니다.

 

Share share = Share.getInstace();

 

 

끝.

반응형

댓글