iOS/Design Pattern

Design Pattern - Singleton Pattern

HaningYa 2020. 8. 9. 00:33
728x90

Singleton Pattern - 싱글톤 패턴

  • class 가 하나의 instance 만 가지도록 제한한다.
  • 모든 class 에 대한 reference 는 하나의 같은 class 에 대한 instance를 참조한다. (Single) 
  • iOS 앱 개발에서 겁나 자주 쓰이고 Apple 이 광범위하게 쓴다.
  • 다른 instance 를 생성하는 shared singleton instance를 제공하는 Singleton Plus 패턴도 자주 쓰인다.

from Design_pattern_by_tutorial (raywenderlich)

Singleton Pattern 언제 사용해야 할까?

  • 하나 이상의 동일 class 의 instance 를 가지게 되면 문제가 생길때
  • 로직상으로 하나 이상의 동일 class 에 대한 instance 를 가지면 안될때

Singleton Plus Pattern 언제 사용해야 할까?

  • shared instance 가 거의 대부분 유용하게 쓰일때
  • 그러면서 custom instance 를 만드는 걸 허용하고 싶을때
  • 예시) FileManager: 파일 시스템의 접근을 관리함. default 라 싱글톤 인스턴스가 있음. 대부분의 경우 default 대신 커스텀한 FileManager 인스턴스를 만들어서 background 쓰레드에서 사용할 것임

Singleton Pattern - Creational Pattern

  • 앞서 다룬 Delegation Pattern 이나 Strategy 패턴은 Bahavior 패턴으로써 하나의 객체가 다른 객체에 대해 명령을 내리는 행위를 하였다.
  • Singleton Pattern 은 Class에 대해 shared 된 instance 를 만드는 패턴이기 때문에 Creational Pattern 에 속한다.

예제) UIApplication

import UIKit

let app = UIApplication.shared
//let app2 = UIApplication() - 주석처리 안하면 에러난다
//왜냐면 싱글톤이라 인스턴스 하나만 만들 수 있다.

 

커스텀 싱글톤 클래스 예제

  1. 먼저 'shared' 라는 public static 프로퍼티를 선언한다. (싱글톤 인스턴스)
  2. init 을 private 하게 선언해 추가적인 인스턴스의 생성을 방지한다.
  3. 싱글톤 인스턴스를 MySingleton.shared를 통해 call 할 수 있다.
  4. 추가적인 MySingleton 인스턴스를 만들면 컴파일 에러가 난다.
public class MySingleton {

	static let shared = MySingleton()
    
    private init() { }
}

let mySingleton = MySingleton.shared

//let mySingleton2 = MySingleton() - 역시 주석을 해제하면 에러가 난다.

Singleton Plus Pattern 예제 - FileManager

let defaultFileManager = FileManager.default
let customFileManager = FileManager()
  • FileManager 는 Singleton property 인 default instance 를 제공한다.
  • 근데 또 새로운 FileManager 인스턴스들을 만들 수 있다.
  • 이게 singleton plus 패턴이라는 증거이다. 

Custom Singleton Plus 예제

  1. 싱글톤에서 했던 것 처럼 shared static property 를 선언한다. 싱글톤 플러스 패턴에서는 이 프로퍼티가 주로 default 라고 정의된다. (근데 원하는데로 이름 정해도 된다.)
  2. 그냥 싱글톤과 달리 init 을 public 으로 선언하여 추가적인 class 인스턴스화를 허용한다.
  3. MySingletonPlus.shared 를 통해 싱글톤 인스턴스에 접근할 수 있다.
  4. 또한 새로운 인스턴스도 만들 수 있다.
public class MySingletonPlus {
	static let shared = MySingletonPlus()
    
    public init() {   }
 }
 let singletonPlus = MySingletonPlus.shared
 let singletonPlus2 = MySingletonPlus()

Singleton Pattern 을 사용할 때 주의할 점

  • 싱글톤 패턴은 과도하게 사용하기 쉽다.
  • 싱글톤 패턴을 사용하고 싶은 상황일때 먼저 다른 방법으로 상황을 해결할 수 있는지 생각해라
  • 예를들어 싱글톤 패턴은 단순히 정보를 view controller 사이에 전달할때는 적합하지 않다.
    --> 그럴땐 싱글톤 대신 initializer 나 property 를 통해 model 을 넘기는 것으로 해결하라
  • 진짜 실제로 진심으로 싱글톤 패턴이 필요하다면 싱글톤 플러스 패턴이 더 적합한지 생각하라
  • 정말 동일 class 에 대해 하나 이상의 instance 를 가지는게 문제를 일으킬지 생각하고 true singleton 을 쓸지 singleton plus 를 쓸지 판단해라
  • code smell 을 주의하라. 쉽게 말하자면 택도 없는 곳에서 싱글톤 패턴 쓰지말고 그냥 보통의 객체를 사용해라

싱글톤 패턴 사용시 단점

  • 싱글톤 패턴의 사용이 문제가 되는 이유 중 하나는 테스팅이다. 
  • 만약 state 가 싱글톤과 같은 전역객체에 저장되어 있다면 테스트의 순서가 중요해 진다.
  • mock 하기도 힘들어 진다.

 

 

 

728x90