Singleton Pattern

pcsoyeon·2021년 12월 1일
0

싱글턴 패턴

특정 용도로 객체를 하나만 생성해서 공용으로 사용하고 싶을 때 사용하는 디자인 유형

하나의 프로그램에서 단 하나의 객체만 있어도 되는 경우 해당 객체를 한번만 생성하고 모든 곳에서 접근 가능하게 해주는 패턴이다. 싱글턴 패턴을 사용할 객체는 한번만 생성되어야 하고 모든 곳에서 접근이 가능한 전역 변수여야 한다.

private으로 한번만 생성하도록 해야하고 static을 통해 타입 프로퍼티를 선언해야 한다. iOS에서 많이 사용하는 방법 중 하나이다.

싱글턴 패턴의 장점

  • 하나의 인스턴스만 존재하는 것을 보장할 수 있다.
  • 한번의 생성으로 여러 곳에서 사용할 수 있기 때문에 불필요한 코드를 줄일 수 있고 메모리를 절약할 수 있다.

싱글턴 패턴의 단점

(단점이라기보다 주의할 점에 가깝다.)

  • 남용하기 쉬운 패턴이므로 전역 객체에 어떠한 상태나 값이 저장되어 있는 경우 테스트 순서에 문제가 생길 수 있다.
  • 굳이 싱글턴 패턴을 사용하지 않아도 될 경우에는 지양해야 한다.
  • 싱글턴 패턴이 너무 많은 일ㅇ르 하거나 많은 데이터를 공유하는 경우 다른 클래스의 인스턴스들 간의 결합도가 높아지므로 개방-폐쇄 원칙이 위배된다. 따라서 수정과 테스트가 어려워진다.

Swift Singleton 패턴의 장점

The free function dispatch_once is no longer available in Swift. In Swift, you can use lazily initialized globals or static properties and get the same thread-safety and called-once guarantees as dispatch_once provided.

objective-c에서 싱글턴을 생성할 때는 dispatch_once를 이용해서 한번만 불리게 해야 하는 작업이 필요하다. 다른 언어에서도 마찬가지지만 싱글턴에르 생성하는 것은 멀티 쓰레딩 환경에서 Thread-Safe하지 않다. 즉, 여러 쓰레드가 동시에 여러 싱글턴을 생성하게 되면 경우에 따라서 Instance가 2개, 3개가 생성될 수 있다.

그러나 Swift의 경우 별도의 작업을 해주지 않아도 static을 사용해서 타입 프로퍼티로 인스턴스를 생성하면 사용 시점에 lazy가 되므로 최초 생성되기 전까지는 메모리에 올라가지 않고 Dispatch_once도 자동 적용된다. (별다른 추가적인 작업이 필요 없이 Instance가 여러개 생성되지 않는 Thread-Safe한 방법이 된다.)

iOS에서 Singleton을 언제 사용하는가?

let screen = UIScreen.main
let userDefault = UserDefaults.standard
let application = UIApplication.shared
let fileManager = FileManager.default
let notification = NotificationCenter.default

이렇게 사용할 수 있다.

구현

Class

class UserInfo {
    var id: String?
    var password: String?
    var name: String?
}

-> User의 정보를 저장하는 클래스

View Controller

// A ViewController
let userInfo = UserInfo()
userInfo.id = "SOKYTE"
// B ViewController
let userInfo = UserInfo()
userInfo.password = "123"
// C ViewController
let userInfo = UserInfo()
userInfo.name = "SOKYTE"

만약, 이런 식으로 A, B, C View Controller에서 각각 Info를 수정한다면 원하는 구현방식이 아닐 것이다. 하나의 인스턴스에서 정보가 저장되어야 하므로 최초 생성될 때 한번만 생성해서 전역에 두고 이후로는 해당 인스턴스에 접근 가능하도록 해야한다.

1. Static 프로퍼티로 Instance 생성하기

class UserInfo {
    static let shared = UserInfo()

    var id: String?
    var password: String?
    var name: String?
}

static을 이용해 인스턴스를 저장할 프로퍼티를 하나 생성하고

2. init 함수 접근제어자를 private로 지정하기

class UserInfo {
    static let shared = UserInfo()

    var id: String?
    var password: String?
    var name: String?

    private init() { }
}

혹시라도 init 함수를 호출해서 Instance를 또 생성하는 것을 막기 위해 init() 함수 접근 제어자를 private로 지정하면 된다.

3. Singleton Class 접근하는 방법

// A ViewController
let userInfo = UserInfo.shared
userInfo.id = "SOKYTE"
// B ViewController
let userInfo = UserInfo.shared
userInfo.password = "123456"
// C ViewController
let userInfo = UserInfo.shared
userInfo.name = "SOKYTE"

어느 클래스에서든지 shared라는 static 프로퍼티로 접근하면 하나의 인스턴스를 공유할 수 있다.

profile
Slowly But Surely

0개의 댓글