같은 객체이지만, 인스턴스 안에 멤버 변수들은 이름은 같아도 각각 다른 값을 부여받을 수 있다.
이를 방지하기 위해 (공유를 하기 위해, 혹은 여러 클래스의 혼동을 방지하기 위해)
하나의 인스턴스 만을 만들어서 그 안에 멤버 변수들의 값을 공유하는 것이다.
더 자세히 말하자면 새로운 생성자를 또 만들지 않고,
딱 한 번만 인스턴스를 사용하여 하나의 생성자 값만을 가질 수 있는 것이다.
이런 점에서 마치 그것과 비슷하다. => Provider
사실 프로바이더와 값을 공유한다는 점? 에서 사용목적이 같을 수 있지만,
프로바이더는 또 하나의 프로바이더 클래스를 만들어 주고,
싱글톤은 해당 클래스 안에서 만들어 주는 개념이라 사용 목적에 따라
더 적합한 것을 고르면 되겠다.
약간 ViewModel과 비슷하게 공유하는 느낌이지만,
이 역시 아예 다른 개념이다.. (이건 개인적인 견해이다.)
더 사용하다 보면 차이점을 알게 될 거이라고 생각한다.
싱글톤 패턴
말 그대로 싱글톤을 이용해서 싱글톤 디자인 패턴을 사용하는 것, 생성자가 여러 번 호출되더라도,
결국엔 최초에 생성된 단 하나의 생성자만 사용되고, (값이 있으면 생성자 호출 시 원래 값으로 리턴)
이를 이용한 디자인 패턴이 바로 싱글톤 패턴이다.
factory
싱글톤 패턴을 사용할 때 쓰는 예약어이다.
factory.. 이름 그대로 해석하면 공장이라는 개념 같은데,
무언가 계속 만들어주는 공장 느낌이 강하지만,
사실 값을 저장해주고 있는 창고와 더 비슷한 개념이라고 보면 된다.
dart 공식 문서를 살펴보면, 새로운 인스턴스를 생성하지 않는 생성자를 구현할 때,
factory 키워드를 사용하라고 명시되어 있다.
팩토리의 특징은 다음과 같다.
1. 전에 이미 생성된 인스턴스가 있다면 원래 값을 return 하여 재사용한다.
2. 하나의 클래스에서 하나의 인스턴스만을 사용한다.
3. 서브 클래스를 리턴할 때 사용할 수 있다.
4 factory 생성자에서는 this에 접근할 수 없다.
좋다 그러면 간단한 예제를 살펴보자.
예제
class Singleton {
int count; //증가해주는 변수
static final Singleton _instance = Singleton._internal();
//_instance 값을 반환한다.
// 값이 있으면 원래 값을 반환한다.
factory Singleton() => _instance;
Singleton._internal() {
//처음 인스턴스를 만들어 주어 실행하는 코드를 여기에 넣어준다.
//초기화 코드
count = 0;
print('Singleton was created.');
}
}
void main() {
var one = Singleton(); //첫 싱글톤 클래스 생성
// 한번더 생성자를 호출한다고 해도
// 위에 첫 생성자를 호출하여, 같은 인스턴스만 넘겨 받게 된다.
// 인스턴스를 공유하게 되는 것이다.
var two = Singleton();
// 각 클래스의 count값 1씩 증가
one.count++;
two.count++;
print(${one.count} + ${two.count});
}
위에 값을 print로 찍어 보면,
2 2
가 나온다.
원래 일반 클래스를 만들고 저런식으로 다른 생성자를 호출하여
똑같이 값을 증가하게 했다면,
각각
1 1
이 나왔을 것이다.
싱글톤은 같은 인스턴스를 공유하고,
일반 클래스는 서로 다른 생성자를 만들어 각각의 인스턴스를 가지기 때문에
위와 같이 공유된 값과 공유되지 않은 값이 나오는 것이다.
보통 싱글톤의 정석 형식은 이런 식으로 생겼다.
class Singleton {
static final Singleton _instance = Singleton._internal();
factory Singleton() {
return _instance;
}
Singleton._internal() { //클래스가 최초 생성될때 1회 발생
//초기화 코드
}
}
static final Singleton _instance = Singleton._internal();