-
싱글톤 패턴(Singleton Pattern)개발 관련/디자인 패턴 2023. 2. 13. 22:42반응형
안녕하세요 Rx입니다 :D
어느덧 23년 2월 중순이네요 개발 시작한지 벌써 1년이 지나갔다니 .. 시간이 참 빠른거같아요
매번 디자인 패턴에 대한 글을 쓰려고 시도했지만 쓰다보면 부족한게 많이 느껴져서 지웠다가 다시 쓰기 반복...🥲
(정리 하는 것도 하다보면 늘게되겠죠 ?👏)
드디어 작성하게되어서 행복하기까지하네요 !
Sigleton Pattern 이란 ?
싱글톤 패턴이란
디자인 패턴 중 생성, 구조, 행위 중 생성에 해당됩니다.
생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고
최초 생성 이후에 호출된 생성자는 최초의 생성자가 생성한 객체를 반환한다.
싱글톤의 특징
불필요한 인스턴스 생성을 방지하여 메모리 낭비를 줄일 수 있고, 생성된 하나의 자원을 공유하고 접근하기 용이하다.
애플 문서에서는 정의과 용도에 대해서 아래와 같이 말하고있네요 !
음향 효과를 재생하기 위한 오디오 채널이나 HTTP 요청을 하는 네트워크 관리자와 같이
앱 간에 공유되는 리소스 또는 서비스에 대한 통합 액세스 포인트를 제공하는 방법으로 자신만의 싱글톤을 만들 수 있습니다.그렇다면 싱글톤 패턴은 왜? 언제 ? 사용을하게될까요 ?
아래 그림과 코드로 설명드려볼게요 !!
User 인스턴스에 이렇게 A,B 모두 참조하고싶은데요 !
class User { var id: String? var pw: String? } class A { var user: User = User() } class B { var user: User = User() } var viewControllerA = A() var viewControllerB = B() viewControllerA.user.id = "Son" // A 의 id Son, pw nil viewControllerB.user.pw = "5678" // B의 id nil, pw 5678 print("id = \(String(describing: viewControllerA.user.id)), pw = \(String(describing: viewControllerA.user.pw))") print("id = \(String(describing: viewControllerB.user.id)), pw = \(String(describing: viewControllerB.user.pw))\n")
하지만 실제로는 A와 B 각각 User 인스턴스가 생성되고있어요
그렇다면 A와 B가 생성된 하나의 User 인스턴스를 사용하기 위해서는 어떤 방법이 있을까요?
첫 번째로는 최초 생성 된 A의 User 인스턴스를 B로 전달 및 할당하는 방법을 사용할 수 있어요
B의 생성자에 User를 받는다던지, 프로퍼티를 통해 할당할 수 있어요
viewControllerB.user = viewControllerA.user viewControllerB.user.pw = "5678"
A와 B 예제는 간단해보이지만,
하지만 복잡한 구조로 갈수록 파라미터 혹은 직접 전달하는 방법은 사용하는데에 있어서 불편한 점이 존재해요 !!
기존의 User 인스턴스를 싱글톤 패턴으로 바꾼 뒤에 차이점을 알아볼게요 !
class User { var id: String? var pw: String? static let shared: User = { let instance = User() // setup code return instance }() private init() {} func getUserInfo() { print("getUserInfo") print(id, pw) } } let userManager = User.shared userManager.getUserInfo() userManager.id = "Son" let userManager2 = User.shared
A와 B 간 User 인스턴스를 전달 없이 생성 된 자원 하나에 접근할 수 있게되었어요 !
Swift에서 Singleton을 만드는 방법
1. static type property 로 인스턴스 생성
class Singleton { static let shared: Singleton() }
class Singleton { static let shared: Singleton = { let instance = Singleton() // setup code return instance }() }
2. init 함수 접근제어자를 private으로 제한하기
class Singleton { static let shared: Singleton() private init {} }
Apple 문서에 lazily initialized only once 구문을 보면서 lazy 키워드가 아니라 static 키워드인데 ?? 라는 의문이 들었다가
Property 공부하면서 봤던거 같아서 바로 공식문서 뒤적뒤적..
그치 ! 저장 타입 프로퍼티는 최초에 lazy하게 초기화되는 특징 때문에 lazily라고 표현하게 되었구나 ! 하고 꺠달음 + 1 해버렸어요 !!
UIKit에서 쓰이는 싱글톤 예시
UIKit에서도 싱글톤 패턴이 적용이 된 예시들이 많습니다.
추가적인 궁금증은
UIKit에서 제공하는 class들을 보면 init 함수 접근제어자를 private 막지않고있습니다.객체 생성은 허용하되, 프로퍼티를 get으로 제한을 하는 식으로 구현한게 아닌가싶은 생각입니당 ..
이유에 대해 아시는 분들 댓글로 이야기 나눠보면 좋겠어요 !!
저도 근거있는 이유가 생기면 재작성하겠습니다 !!
*참고
Swift) 프로퍼티 정복하기 (3/4) - 타입 프로퍼티(Type Property) - 개발자 소들이
https://babbab2.tistory.com/66
Swift) 싱글톤 패턴(Singleton Pattern) - 개발자 소들이
https://docs.swift.org/swift-book/LanguageGuide/Properties.html
https://developer.apple.com/documentation/swift/managing-a-shared-resource-using-a-singleton