싱글턴 패턴을 사용하는 간단한 예제 입니다.
한개의 클래스로 만든 객체는 단 한개여야만 한다.
라는 규칙을 가진 디자인 패턴이다.- 프로그램 전체에 단 하나의 전역 객체를 만들어놓고, 전역적으로 이 하나의 객체에만 접근할 수 있도록 하는 것이다.
URLSession,shared
: 네트워크 처리를 할 때 URLSession 객체의 shared에 접근할 때 사용하보았다.UserDegaults.standard
: userDefaults 에서 기본적으로 공유하고 있는 standard 저장소에 접근하여 읽고 쓰기위해 접근할 때 사용해보았다.
static let
키워드를 사용하여 자기 자신을 선언한다.static
키워드를 사용함으로써 전역적으로 사용할 수 있다.
class SomeSingleton {
static let shared = SomeSingleton()
private init() {}
...
}
init
을private
으로 설정함으로써 유일성을 보장할 수 있다.
즉, private init() { }
을 작성함으로써 다른 곳에서는 싱글턴 객체를 초기화하거나 생성할 수 없다.
이것을 작성하주지 않으면, static let
으로 선언한 인스턴스를 사용할 때마다 객체가 매던 생성된다.
이를 방지하기 위해 사용한다.
전역변수를 사용하여 인스턴스를 사용하게 되면,
- 사용시 점에 초기화가 되는 장점이 있고
- GCD의 dispatch once도 자동으로 적용되어 인스턴스가 생성되므로
thread-safe
하다.
메모리를 단 한번만 사용한다.
- 객체가 단 한번만 만들어지기 때문에 메모리 관리하기가 편하고, 한번 만들어 둔 객체를 재사용할 수 있다.
- class로 만든 객체를 사용했을 때 메모리에서 해제되지 않아 메모리 누수를 찾느라 고생할 일이 없어진다.
객체 접근 시간이 줄어든다.
- 다시 메모리를 할당, 초기화하는 과정이 필요 없기 때문이다.
전역 범위에서 상태, 데이터 전달이 쉬워진다.
- 단 하나의 객체만 있기에 동시성 문제만 발생하지 않도록 짠다면
- 어디에서든 접근할 수 있기 때문에 상태표시를 하거나, 데이터를 공유하기에 좋다.
테스트가 어렵다.
- 단 하나의 객체만 유지함으로써 유일성을 보장한다는 의도는 좋지만, 객체 생성을 제한해버리기에 테스트응 mock 객체를 만들기 어렵다.
- 관련 로직을 테스트하기 어렵고 곤란해질 수 있다.
의존성이 생긴다.
- 전역적으로 이곳저곳에서 쉽게 접근이 가능한 만큼, 어떤 객체와 어디에서 연결되어있는지 찾기 힘들 수 있다.
multi-thread 환경에서 위험할 수 있다.
multi-thread
환경에서는 싱글턴 객체가 2개가 생기게 될 수 있다.- 또한 객체 내부 데이터를 동기적으로 처리하지 않으면 여러 객체의 동시접근으로 데이터가 꼬일 수 있다.
사용을 하고자 한다면
- 동시성을 신경써서 설계
- 객체의 역할과 책임을 최소한으로 설정
- 정말 필요한 것만 지니고 있도록 구현
하여 다른 객체에 영향을 주지 않도록 하자!