본문 바로가기

프로그래밍/Design Pattern

생성 패턴 - 싱글톤(Singleton) 1

singleton은 다음과 같은 뜻을 갖고 있다. 

디자인 패턴에서의 싱글톤도 singleton의 사전적 의미와 크게 다르지 않다. 

 

싱글톤을 살펴보기 전에 다음 코드를 살펴보자. 

// NonSingleton.swift

class NonSingleton {
    var number: Int
    
    init(_ number: Int = 0) {
        self.number = number
        print("number가 \(number)인 인스턴스 생성")
    }
}

 

해당 클래스의 인스턴스는 number라는 하나의 속성을 갖는다. 이 클래스를 이용해 두 개의 인스턴스를 다음과 같이 생성할 수 있다. 두 객체가 포함하는 각각의 number 변수는 1이라는 같은 값을 갖고 있지만, 두 객체는 명백히 다르다. 따라서 obj1에 포함되어 있는 변수를 변경시켜도 이는 obj2에 전혀 영향을 못 미친다. 

var obj1 = NonSingleton(1)  // number가 1인 인스턴스 생성
var obj2 = NonSingleton(1)  // number가 1인 인스턴스 생성
obj1 === obj2 ? print("같은 인스턴스") : print("다른 인스턴스") // 다른 인스턴스

obj1.number = 3
print(obj2.number)          // 1

 

하지만 우리는 종종 값을 공유하고 싶을 때가 있다. 이럴 때 대표적으로 Static을 이용하거나 싱글톤을 이용할 수 있다. 

 

먼저 Static을 이용하여 값을 공유하는 방법이다. (NonSingleton 클래스를 수정하였다)

// NoneSingleton.swift

class NonSingleton {
    static var number: Int = 0
}

 

 

// main.swift

// Static Class를 이용한 값 공유
NonSingleton.number = 1
print(NonSingleton.number)      // 1
NonSingleton.number = 3
print(NonSingleton.number)      // 3

이렇듯 객체를 따로 생성할 필요 없이 클래스에서 number 변수에 접근할 수 있고, 이는 프로그램 전체에서 공유될 수 있다. 

 

 

다음은 싱글톤을 사용하여 값을 공유하는 방법이다. 

 

먼저 값을 공유하기 위해서는, 클래스의 인스턴스가 오직 한 번만 생성된다는 것을 보장해줘야 한다. 이를 위해 인스턴스를 생성하는 init 메서드의 접근 수준을 private으로 바꾸고(외부에서 인스턴스 생성을 제한하기 위해) getInstance라는 메서드에 인스턴스 생성을 위임하였다. getInstance 메서드는 인스턴스가 생성된 적이 없을 때만 인스턴스를 생성하도록 관리해 준다(getInstance는 객체가 생성되지 않아도 사용할 수 있도록 정적으로 선언해 주었다). 또, 인스턴스의 생성 여부를 판단하기 위해 instance라는 속성을 두었다. 

// Singleton.swift

class Singleton {
    private static var instance: Singleton?         // 인스턴스가 기존에 생성되었는지 확인하기 위한 속성
    var number: Int = 0
    
    private init() {
        print("인스턴스 생성 됨")
    }
    
    // 인스턴스가 생성되지 않아도 실행가능하도록 정적으로 선언
    public static func getInstance() -> Singleton {
        if self.instance == nil {
            self.instance = Singleton()
        }
        
        print("인스턴스 반환 됨")
        return instance!
    }
}

 

그리고 다음과 같은 코드를 실행해 보자. 

main.swift

// Singleton Class를 이용한 값 공유
var obj1 = Singleton.getInstance()
var obj2 = Singleton.getInstance()
obj1 === obj2 ? print("같은 인스턴스") : print("다른 인스턴스") // 같은 인스턴스

obj1.number = 3
print(obj2.number)          // 3

실행 결과, obj1과 obj2이 같은 인스턴스라는 것이 확인되었다. 

그래서 obj1을 통해 number 속성을 변경해도, obj2를 통해 변경된 number에 접근할 수 있게 된다. 

 

이렇듯 싱글톤과 static을 이용한 공유를 살펴보았다. 하지만 두 방법은 여러 차이점들이 있다. 두 방법 중에 어느 하나가 절대적으로 좋다고는 할 수 없고 상황에 따라 적절히 활용하는 지혜가 필요하다. 

 

다음 시간에는 두 방법의 차이점에 대해 살펴보겠다. 

'프로그래밍 > Design Pattern' 카테고리의 다른 글

생성 패턴 - 팩토리(Factory)  (0) 2021.07.02
디자인 패턴(Design Pattern)  (0) 2021.07.01