1.1. Intent ¶
ํด๋์ค๋ก ํ์ฌ๊ธ ์ค์ง ํ๋์ ์ธ์คํด์ค๋ง์ ๊ฐ์ง๊ฒ ํ๋ฉฐ, ์ด๋์๋ ์ง ์ ๊ทผ ๊ฐ๋ฅํ๋๋ก ํ๋ค.
1.2. Motivation ¶
๋ช๋ช ํด๋์ค๋ค์ ๋ํด์ ์ค์ง ํ๋์ ์ธ์คํด์ค ๋ง์ ๊ฐ์ง๋ ๊ฒ์ ์ค์ํ ์ผ์ด๋ค. ์๋ฅผ ๋ค๋ฉด, ์ด๋ค ์์คํ
์์ ์๋ง์ ํ๋ฆฐํฐ๋ค์ด ์๋๋ผ๋ ๊ฑฐ๊ธฐ์๋ ๋จ ํ๋์ ํ๋ฆฐํฐ ์คํ๋ฌ๋ง์ด ์์ด์ผ ํ๋ค. OS์์ ๋์๊ฐ๋ ํ์ผ์์คํ
์ด๋ ์๋์ฐ ๋งค๋์ ์ ๊ฒฝ์ฐ๋ ์ค์ง ํ๋์ฌ์ผ ํ๋ค (๋์์ 2-3๊ฐ์ ์๋์ฐ๋งค๋์ ๊ฐ ๋์ง ์๋๋ค.) ๋์งํธ ํํฐ์ ๊ฒฝ์ฐ์๋ A/D converter๋ ๋จ ํ๋๋ฅผ ๊ฐ์ง๋ค.
์ด๋ป๊ฒ ์ฐ๋ฆฌ๋ ํด๋์ค๋ก ํ์ฌ๊ธ ๋จ ํ๋์ ์ธ์คํด์ค๋ง์ ๊ฐ์ง๋๋ก ๋ณด์ฅํด์ค ์ ์์๊น? ๊ทธ๋ฆฌ๊ณ ๊ทธ๋ฌํ ์ธ์คํด์ค๋ฅผ ์ฝ๊ฒ ์ ๊ทผํ๊ฒ ํ ์ ์์ ๊ฒ์ธ๊ฐ? global ๋ณ์๋ก ๋ ๊ฒฝ์ฐ ์ด๋์๋ ์ง ์ ๊ทผ๊ฐ๋ฅํ๊ฒ ์ง๋ง, global ๋ณ์๋ ๋จ์ผ ์ธ์คํด์ค๋ง์ ๊ฐ์ง๋๋ก ํ ์ ์๋ค.
๋ ์ข์ ๋ฐฉ๋ฒ์ ํด๋์ค ์์ ์ผ๋ก ํ์ฌ๊ธ ์๊ธฐ์์ ์ ๋จ์ผ ์ธ์คํด์ค๋ฅผ ์ ์งํ๋๋ก ๋ง๋๋ ๊ฒ์ด๋ค. ์ด ํด๋์ค๋ ์ธ์คํด์ค๊ฐ ์์ฑ๋ ๋ ์์ฒญ์ ๊ฐ๋ก์ฑ์ผ๋ก์ ๋จ์ผ ์ธ์คํด์ค๋ก ๋ง๋ค์ด์ง๋ ๊ฒ์ ๋ณด์ฆํ๋ค. ๋ํ, ์ธ์คํด์ค์ ์ ๊ทผํ๋ ๋ฐฉ๋ฒ๋ ์ ๊ณตํ๋ค. ์ด๊ฒ์ด ๋ฐ๋ก SingletonPattern์ด๋ค.
1.3. Applicability ¶
SingletonPattern์ ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ์ ์ฌ์ฉํ๋ค.
- ํด๋์ค๊ฐ ์ ํํ ์ค์ง ํ๋์ ์ธ์คํด์ค๋ง์ด ์กด์ฌํด์ผ ํ ๋. ๊ทธ๋ฆฌ๊ณ ์ ์๋ ค์ง ์์ธ์ค ๋ฐฉ๋ฒ์ผ๋ก ์ด๋์๋ ์ง ์ ๊ทผ ํ ์ ์์ด์ผ ํ๋ค.
- ๋จ์ผ ์ธ์คํด์ค๊ฐ ์๋ธํด๋์ฑ์ ์ํด ํ์ฅ๊ฐ๋ฅํด์ผ ํ ๊ฒฝ์ฐ. ๊ทธ๋ฌ๋ฉด ํด๋ผ์ด์ธํธ๋ ๊ทธ๋ค์ ์ฝ๋ ์์ ์์ด ํ์ฅ๋ ์ธ์คํด์ค๋ฅผ ์ฌ์ฉํ ์ ์์ด์ผ ํ๋ค.
1.5. Participants ¶
- Singleton
- Instance operation (ํด๋์ค์ ๋ฉ์๋)์ ์ ์ํ๋ค. Instance ๋ ํด๋ผ์ด์ธํธ์๊ฒ ํด๋น Singleton์ ์ ์ผํ ์ธ์คํด์ค๋ฅผ ์ ๊ทผํ ์ ์๋๋ก ํด์ค๋ค.
- Singleton ์์ ์ ์ ์ผํ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ์ฑ
์์ ๊ฐ์ง๋ค.
- Instance operation (ํด๋์ค์ ๋ฉ์๋)์ ์ ์ํ๋ค. Instance ๋ ํด๋ผ์ด์ธํธ์๊ฒ ํด๋น Singleton์ ์ ์ผํ ์ธ์คํด์ค๋ฅผ ์ ๊ทผํ ์ ์๋๋ก ํด์ค๋ค.
1.6. Collaborations ¶
- ํด๋ผ์ด์ธํธ๋ ์ค์ง Singleton์ Instance operation์ผ๋ก๋ง Singleton ์ธ์คํด์ค์ ์ ๊ทผํ ์ ์๋ค.
1.7. Consequences ¶
SingletonPattern์ ์ฌ๋ฌ๊ฐ์ง ์ฅ์ ์ ๊ฐ์ง๋ค.
- ํด๋์ค์ ๋ํ ์ ๊ทผ์ด ์ค์ง ํ๋์ ์ธ์คํด์ค์๊ฒ๋ก ์ ํ๋๋ค. Singleton ํด๋์ค๋ ์๊ธฐ ์์ ์ ๋จ์ผ ์ธ์คํด์ค๋ฅผ ์บก์ํํ๊ธฐ ๋๋ฌธ์, ํด๋ผ์ด์ธํธ๊ฐ ์ธ์ , ์ด๋ป๊ฒ ์ ๊ทผํ๋์ง ๊ทธ ์ ๊ทผ์ด ์๊ฒฉํ๊ฒ ์ ์ด๋๋ค.
- namespace๋ฅผ ์ค์ธ๋ค. SingletonPattern์ global variable์ ์ค์์ผ๋ก์ global variable๋ก ์ธํ namespace์ ๋ญ๋น๋ฅผ ์ค์ธ๋ค.
- ๋ช
๋ น์ด์ ํํ์ ํ์ฅ์ํฌ ์ ์๋ค. Singleton class๋ subclass๋ ์ ์๊ณ , ์ด ํ์ฅ๋ ํด๋์ค์ ์ธ์คํด์ค๋ฅผ ๊ฐ์ง๊ณ ์ดํ๋ฆฌ์ผ์ด์
์ ์ค์ ํ๋ ๊ฒ์ ์ฝ๋ค. run-time์ค์ ํ์ํ ๊ฒฝ์ฐ์๋ ๊ฐ๋ฅํ๋ค.
- ์ฌ๋ฌ๊ฐ์ ์ธ์คํด์ค๋ฅผ ํ์ฉํ๋ค. ํ๋ก๊ทธ๋๋จธ์ ๋ง์์ ๋ฐ๋ผ ์ฝ๊ฒ Singleton class์ ์ธ์คํด์ค๋ฅผ ํ๋์ด์์ ๋ ์๋ ์๋๋ก ํ ์ ์๋ค. ๊ฒ๋ค๊ฐ ์ดํ๋ฆฌ์ผ์ด์
์ด ์ฌ์ฉํ๋ ์ธ์คํด์ค๋ค์ ์ ์ดํ๊ธฐ ์ํด ๋์ผํ ์ ๊ทผ๋ฐฉ๋ฒ์ ์ทจํ ์ ์๋ค. ๋จ์ง Singleton ์ธ์คํด์ค์ ์ ๊ทผํ๋ ๊ฒ์ ๋ณด์ฅํ๋ operation๋ง ์์ ํ๋ฉด ๋๋ค.
- class operation ๋ณด๋ค ๋ ์ ์ฐํ๋ค. ํจํค์ง์์ Singleton์ ๊ธฐ๋ฅ์ ์ํํ๊ธฐ์ํ ๋๋ค๋ฅธ ๋ฐฉ๋ฒ์ class operation๋ค์ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค. (C++์์์ static ํจ์๋ Smalltalk์์์ class method ๋ฑ๋ฑ) ํ์ง๋ง, ์ด๋ฌํ ์ธ์ด์ ์ธ ํ
ํฌ๋๋ค์ ์ฌ๋ฌ๊ฐ์ ์ธ์คํด์ค๋ฅผ ํ์ฉํ๋ ๋์์ธ์ผ๋ก ๋ฐ๊พธ๊ธฐ ํ๋ค์ด์ง๋ค. ๊ฒ๋ค๊ฐ C++์์์ static method๋ virtual์ด ๋ ์ ์์ผ๋ฏ๋ก, subclass๋ค์ด override ํ ์ ์๋ค.
1.8. Implementation ¶
SingletonPattern ์ ์ฌ์ฉํ ๋ ๊ณ ๋ คํด์ผ ํ ์ฌํญ๋ค์ด ์๋ค.
1. unique instance์์ ๋ณด์ฆํ๋ ๊ฒ. SingletonPattern์ ๊ฒฝ์ฐ๋ ์ผ๋ฐ ํด๋์ค์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ๊ฐ๋ค. ํ์ง๋ง ํด๋์ค๋ ๋ ๋จ์ผ ์ธ์คํด์ค๊ฐ ์ ์ง๋๋๋ก ํ๋ก๊ทธ๋๋ฐ๋๋ค. ์ด๋ฅผ ๊ตฌํํ๋ ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ์ ์ธ์คํด์ค๋ฅผ ๋ง๋๋ operation์ class operations์ผ๋ก ๋๋ ๊ฒ์ด๋ค. (static member function์ด๊ฑฐ๋ class method) ์ด operation์ unique instance๋ฅผ ๊ฐ์ง๊ณ ์๋ ๋ณ์์ ์ ๊ทผํ๋ฉฐ ์ด๋ ์ด ๋ณ์์ ๊ฐ (์ธ์คํด์ค)๋ฅผ ๋ฆฌํดํ๊ธฐ ์ ์ ์ด ๋ณ์๊ฐ unique instance๋ก ์ด๊ธฐํ ๋์ด์ง๋ ๊ฒ์ ๋ณด์ฅํ๋ค. ์ด๋ฌํ ์ ๊ทผ์ singleton์ด ์ฒ์ ์ฌ์ฉ๋์ด์ง ์ ์ ๋ง๋ค์ด์ง๊ณ ์ด๊ธฐํ๋จ์ผ๋ก์ ๋ณด์ฅ๋๋ค.
๋ค์์ ์๋ฅผ ๋ณด๋ผ. C++ ํ๋ก๊ทธ๋๋จธ๋ Singleton class์ Instance operation์ static member function์ผ๋ก ์ ์ํ๋ค. Singleton ๋ํ static member ๋ณ์์ธ _instance๋ฅผ ์ ์ํ๋ค. _instance๋ Singleton์ ์ ์ผํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ์ด๋ค.
Singleton class๋ ๋ค์๊ณผ ๊ฐ์ด ์ ์ธ๋๋ค.
~cpp class Singleton { public: static Singleton* Instance (); protected: Singleton (); private: static Singleton* _instance; };
๋์๋๋ ์ค์ ๊ตฌํ๋ถ๋ ๋ค์๊ณผ ๊ฐ๋ค.
~cpp Singleton* Singleton::_instance = 0; Singleton* Singleton::Instance () { if (_instance == 0) { _instance = new Singleton; } return _instance; }
ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ Client๋ singleton์ Instance operation์ ํตํด ์ ๊ทผํ๋ค. _instance ๋ 0๋ก ์ด๊ธฐํ๋๊ณ , static member function ์ธ Instance๋ ๋จ์ผ ์ธ์คํด์ค _Instance๋ฅผ ๋ฆฌํดํ๋ค. ๋ง์ผ _instance๊ฐ 0์ธ ๊ฒฝ์ฐ unique instance๋ก ์ด๊ธฐํ์ํค๋ฉด์ ๋ฆฌํดํ๋ค. Instance๋ lazy-initalization์ ์ด์ฉํ๋ค. (Instance operation์ด ์ต์ด๋ก ํธ์ถ๋์ด์ ๊น์ง๋ ๋ฆฌํดํ unique instance๋ ์์ฑ๋์ง ์๋๋ค.)
์์ฑ์๊ฐ protected ์์ ์ฃผ๋ชฉํ๋ผ. client ๊ฐ ์ง์ Singleton์ ์ธ์คํด์คํ ํ๋ ค๊ณ ํ๋ฉด compile-time์ ์๋ฌ๋ฅผ ๋ฐ์ํ ๊ฒ์ด๋ค. ์์ฑ์๋ฅผ protected ๋ก ๋ ์ผ๋ก์ ๋ ๋จ์ผ ์ธ์คํด์ค๋ก ๋ง๋ค์ด์ง๋๋ก ๋ณด์ฆํด์ค๋ค.
๋ ๋์๊ฐ, _instance ๋ Singleton ๊ฐ์ฒด์ ํฌ์ธํฐ์ด๋ฏ๋ก, Instance member function์ ์ด ํฌ์ธํฐ๋ก ํ์ฌ๊ธ Singleton ์ subclass๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ํ ์ ์๋ค.
C++ ๊ตฌํ์ ๋ํด์๋ ์๊ฐํด์ผ ํ ๊ฒ์ด ๋ ์๋ค. singleton ์ global์ด๋ static ๊ฐ์ฒด๋ก ๋๊ณ ๋ ๋ค ์๋ ์ด๊ธฐํ๋๋๋ก ๋๋๋ ๊ฒ์ผ๋ก ์ถฉ๋ถํ์ง ์๋ค. ์ด์ ๋ํด์๋ 3๊ฐ์ง ์ด์ ๊ฐ ์๋ค.
- (a) static ๊ฐ์ฒด์ ์ ์ผํ ์ธ์คํด์ค๊ฐ ์ ์ธ๋์ด์ง ๊ฒ์ด๋ผ๊ณ ๋ณด์ฅํ ์ ์๋ค.
- (b) ๋ชจ๋ singleton๋ค์ด static initialization time ๋ ์ธ์คํด์ค๋๊ธฐ ์ํ ์ถฉ๋ถํ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์์ง ์์์๋ ์๋ค. singleton์ ํ๋ก๊ทธ๋จ์ด ์คํ๋ ๋ ๊ทธ๋ฌํ ์ ๋ณด๋ฅผ ์ป์ ์ ์๋ค.
- (c) C++ ์ global ๊ฐ์ฒด์ ์์ฑ์๊ฐ translation unit๋ฅผ ํตํ๋ฉด์ ํธ์ถ๋ ๋์ ์์๋ฅผ ์ ์ํ์ง ์๋๋คES90. ์ด๋ฌํ ์ฌ์ค์ singleton ๋ค ๊ฐ์๋ ์ด๋ ํ ์์กด์ฑ๋ ์กด์ฌํ ์ ์์์ ์๋ฏธํ๋ค. ๋ง์ผ ๊ทธ๋ด ์ ์๋ค๋ฉด, ์๋ฌ๋ฅผ ํผํ ์ ์๋ค.
Smalltalk์์ unique instance๋ฅผ ๋ฆฌํดํ๋ functiond์ Singleton ํด๋์ค์ class method๋ก ๊ตฌํ๋๋ค. ๋จ์ผ ์ธ์คํด์ค๊ฐ ๋ง๋ค์ด์ง๋ ๊ฒ์ ๋ณด์ฅํ๊ธฐ ์ํด์ new operation์ overrideํ๋ค. The resulting Singleton class might have the following two class methods, where SoleInstance is a class variable that is not used anywhere else:
~cpp new self error: 'cannot create new object' default SoleInstance isNil ifTrue: [SoleInstance := super new]. ^ SoleInstance
2. Singleton class๋ฅผ subclassing ํ๊ธฐ ๊ด๋ จ. ์ฃผ๋ ์ฃผ์ ๋ ํด๋ผ์ด์ธํธ๊ฐ singleton ์ subclass๋ฅผ ์ด์ฉํ ์ ์๋๋ก subclass๋ค์ unique instance๋ฅผ ์ค์ ํ๋ ๋ถ๋ถ์ ์๋ค. ํ์์ ์ผ๋ก, singleton ์ธ์คํด์ค๋ฅผ ์ฐธ์กฐํ๋ ๋ณ์๋ ๋ฐ๋์ subclass์ ์ธ์คํด์ค๋ก ์ด๊ธฐํ๋์ด์ ธ์ผ ํ๋ค. ๊ฐ์ฅ ๋จ์ํ ๊ธฐ์ ์ Singleton์ Instance operation์ ์ฌ์ฉํ๊ธฐ ์ํ๋ singleton์ ์ ํด๋๋ ๊ฒ์ด๋ค. Sample Code์๋ ํ๊ฒฝ๋ณ์๋ค์ ๊ฐ์ง๊ณ ์ด ๊ธฐ์ ์ ์ด๋ป๊ฒ ๊ตฌํํ๋์ง ๋ณด์ฌ์ค๋ค.
Singleton์ subclass๋ฅผ ์ ํํ๋ ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ Instance ๋ฅผ Parent class์์ ๋นผ ๋ธ๋ค, (e.g, MazeFactory) subclass ์ Instance๋ฅผ ๊ตฌํํ๋ ๊ฒ์ด๋ค. ์ด๋ C++ ํ๋ก๊ทธ๋๋จธ๋ก ํ์ฌ๊ธ link-time์์ singleton์ class๋ฅผ ๊ฒฐ์ ํ๋๋ก ํด์ค๋ค. (e.g, ๊ฐ๊ฐ ๋ค๋ฅธ ๊ตฌํ๋ถ๋ถ์ ํฌํจํ๋ ๊ฐ์ฒดํ์ผ์ linkingํจ์ผ๋ก์จ.)
์ด๋ฌํ link-approach ๋ฐฉ๋ฒ์ link-time๋ singleton class ์ ์ ํ์ ๊ณ ์ ์์ผ๋ฒ๋ฆฌ๋ฏ๋ก, run-time์์ singleton class์ ์ ํ์ ํ๋ค๊ฒ ํ๋ค. subclass๋ฅผ ์ ํํ๊ธฐ ์ํ ์กฐ๊ฑด๋ฌธ๋ค (switch-case ๋ฑ๋ฑ)์ ํ๋ก๊ทธ๋จ์ ๋ ์ ์ฐํ๊ฒ ํ ์ ์์ง๋ง, ๊ทธ๊ฒ ๋ํ ์ด์ฉ๊ฐ๋ฅํ singleton class๋ค์ ๋ฌถ์ด๋ฒ๋ฆฌ๊ฒ ๋๋ค. ์ด ๋๊ฐ์ง์ ๋ฐฉ๋ฒ ๋ค ๊ทธ๋ค์ง ์ ์ฐํ ๋ฐฉ๋ฒ์ ์๋๋ค.
๋์ฑ๋ ์ ์ฐํ ์ ๊ทผ ๋ฐฉ๋ฒ์ผ๋ก registry of singletons ์ด ์๋ค. ๊ฐ๋ฅํ Singleton class๋ค์ ์งํฉ์ ์ ์ํ๋ Instance operation์ ๊ฐ์ง๋ ๊ฒ ๋์ , Singleton class๋ค์ ์ ์๋ ค์ง registry ์ ๊ทธ๋ค์ singleton instance๋ฅผ ๋ฑ๋กํ๋ ๊ฒ์ด๋ค.
registry ๋ string name ๊ณผ singletons ์ mapping ํ๋ค. singleton์ instance๊ฐ ํ์ํ ๊ฒฝ์ฐ, registry์ string name์ผ๋ก ํด๋น singleton ์ ์์ฒญํ๋ค. registry๋ ๋์ํ๋ singleton์ ์ฐพ์์ (๋ง์ผ ์กด์ฌํ๋ค๋ฉด) ๋ฆฌํดํ๋ค. ์ด๋ฌํ ์ ๊ทผ๋ฐฉ๋ฒ์ ๋ชจ๋ ๊ฐ๋ฅํ Singleton class๋ค์ด๋ instance๋ค์ Instance operation์ด ์ ํ์๊ฐ ์๋๋ก ํ๋ค. ํ์ํ ๊ฒ์ registry์ ๋ฑ๋ก๋ ๋ชจ๋ Singleton class๋ค์ ์ํ ์ผ๋ฐ์ ์ธ interface์ด๋ค.
~cpp class Singleton { public: static void Register (const char* name, Singleton*); static Singleton* Instance (); protected: static Singleton* Lookup (const char* name); private: static Singleton* _instance; static List<NameSingletonPair>* _registry; };
Register operation์ ์ฃผ์ด์ง string name์ผ๋ก Singleton instance๋ฅผ ๋ฑ๋กํ๋ค. registry๋ฅผ ๋จ์ํ์ํค๊ธฐ ์ํด ์ฐ๋ฆฌ๋ NameSingletonPair ๊ฐ์ฒด์ ๋ฆฌ์คํธ์ instance๋ฅผ ์ ์ฅํ ๊ฒ์ด๋ค. ๊ฐ NameSingletonPair๋ name๊ณผ instance๋ฅผ mappingํ๋ค. Lookup operation์ ์ฃผ์ด์ง ์ด๋ฆ์ ๊ฐ์ง๊ณ singleton์ ์ฐพ๋๋ค. ์ฐ๋ฆฌ๋ ๋ค์์ ์ฝ๋์์ environment variable์ด ์ํ๋ singleton์ ์ด๋ฆ์ ๋ช
์ํ๊ณ ์์์ ์๊ฐํ ์ ์๋ค.
~cpp Singleton* Singleton::Instance () { if (_instance == 0) { const char* singletonName = getenv("SINGLETON"); // user or environment supplies this at startup _instance = Lookup (singletonName); // Lookup returns 0 if there's no such singleton } return _instance; }์ด๋์์ Singleton class๋ค์ด ๊ทธ๋ค์ ๋ฑ๋กํ๋๊ฐ? ํ๊ฐ์ง ๊ฐ๋ฅ์ฑ์ ๊ทธ๋ค์ ์์ฑ์์์๋ค. ์๋ฅผ๋ค์ด singleton์ subclass์ธ MySingleton ์ ๋ค์๊ณผ ๊ฐ์ด ๊ตฌํํ ์ ์๋ค.
~cpp MySingleton::MySingleton () { // ... Singleton::Register ("MySingleton", this); }๋ฌผ๋ก , ์ฝ๋ ์ด๋์์ ๊ฐ ํด๋์ค๋ฅผ ์ธ์คํด์คํํ์ง ์์ผ๋ฉด ์์ฑ์๋ ํธ์ถ๋์ง ์์ ๊ฒ์ด๋ค. C++์์๋ MySingleton์ static instance๋ฅผ ์ ์ํจ์ผ๋ก์ ์ด ๋ฌธ์ ๋ฅผ ์ ํด๊ฒฐํ ์ ์๋ค. ์๋ฅผ ๋ค์ด, MySingleton ํด๋์ค์ ๊ตฌํ๋ถ๋ฅผ ํฌํจํ๋ ํ์ผ์ ๋ค์๊ณผ ๊ฐ์ด ์ ์ํ๋ฉด ๋๋ค.
~cpp static MySingleton theSingleton;
๋ ์ด์ Singleton class ๋ singleton ๊ฐ์ฒด๋ฅผ ๋ง๋ค ์ฑ
์์ด ์๋ค. ๊ทธ ๋์ ์ด์ Singleton ์ ์ฃผ๋ ์ฑ
์์ ์์คํ
๋ด์์ ์ ํํ singleton ๊ฐ์ฒด๋ฅผ ์ ๊ทผ๊ฐ๋ฅํ๋๋ก ํด์ฃผ๋ ๊ฒ์ด๋ค. static object approach๋ ์ฌ์ ํ ๋จ์ ์ด ์กด์ฌํ๋ค. ๋ชจ๋ ๊ฐ๋ฅํ Singleton subclass๋ค์ ์ธ์คํด์ค๋ค์ด ์์ฑ๋์ด์ง๋์ง, ๊ทธ๋ ์ง ์์ผ๋ฉด register๋์ด์๋ ์๋๋ค๋ ๊ฒ์ด๋ค.
1.9. Sample Code ¶
๋ฏธ๋ก๋ฅผ ๋ง๋๋ MazeFactory ํด๋์ค๋ฅผ ์ ์ํ๋ค๊ณ ํ์. MazeFactory ๋ ๋ฏธ๋ก์ ๊ฐ๊ฐ ๋ค๋ฅธ ๋ถ๋ถ๋ค์ ๋ง๋๋ interface๋ฅผ ์ ์ํ๋ค. subclass๋ค์ ๋ ํน๋ณํ๋ product class๋ค์ instance๋ค์ ๋ฆฌํดํ๊ธฐ ์ํ opeation๋ค์ ์ฌ์ ์ํ ์ ์๋ค. ์๋ฅผ ๋ค๋ฉด BombedWall ๊ฐ์ฒด๋ ์ผ๋ฐ์ ์ธ Wall๊ฐ์ฒด๋ฅผ ๋์ ํ๋ค.
์ฌ๊ธฐ์ SingletonPattern๊ณผ ๊ด๋ จ ๋๋ ๋ด์ฉ์ Maze application์ ๋จ ํ๋์ maze factory๋ฅผ ํ์๋ก ํ๋ค๋ ๊ฒ๊ณผ ๊ทธ maze factory์ ์ธ์คํด์ค๋ ์ด๋์๋ ์ง maze์ ๋ถ๋ถ์ ๋ง๋ค ์ ์๋๋ก ์กด์ฌํด์ผ ํ๋ค๋ ๊ฒ์ด๋ค. ์ด๋ฌํ ๋๊ฐ ๋ฐ๋ก SingletonPattern์ ๋์
ํ ๋์ด๋ค. MazeFactory๋ฅผ Singleton์ผ๋ก ๊ตฌํํจ์ผ๋ก์จ, global variable์ ๋ํ ์ฌ์ ๋ ฌ์ ํ ํ์๊ฐ ์์ด maze ๊ฐ์ฒด๋ฅผ ๋ง๋ค๋ ํ์ํ MazeFactory๋ฅผ globalํ๊ฒ ์ ๊ทผํ ์ ์๋ค.
์ผ๋จ ๋จ์ํ๊ฒ, MazeFactory์ subclassing์ด ํ์์๋ค๊ณ ๊ฐ์ ํ์. (์ ์ ํ subclassing๊ณผ ๊ด๋ จ, ๋์์ ์ธ ๋ฐฉ๋ฒ์ ๋ํด ๊ณ ๋ คํด ๋ณผ ๊ฒ์ด๋ค.) C++ ์์๋ static operation์ธ Instance์ unique instance๋ฅผ ์ฐธ์กฐํ๋ static member์ธ _instance ๋ฅผ ์ถ๊ฐํจ์ผ๋ก์ Singleton ํด๋์ค๋ฅผ ๊ตฌํํ ์ ์๋ค. ์์ Implementation์์๋ ์ธ๊ธํ๋ฏ์ด ๋ฐ๋์ ์์ฑ์๋ protected๋ก ๋ ์ผ๋ก์ ์ฐ๋ฐ์ ์ผ๋ก ํ๋์ด์์ ์ธ์คํด์ค๊ฐ ์์ฑ๋๋ ๊ฒ์ ๋ง๋๋ค.
~cpp class MazeFactory { public: static MazFactory* Instance (); // existing interface goes here protected: MazeFactory (); private: static MazeFactory* _instance; };
๋์๋๋ ํด๋์ค์ ์ค์ ๊ตฌํ๋ถ๋ถ์ ๋ค์๊ณผ ๊ฐ๋ค.
~cpp MazeFactory* MazeFactory::_instance = 0; MazeFactory* MazeFactory::Instance () { if (_instance == 0) { _instance = new MazeFactory; } return _instance; }
์, ์ด์ MazeFactory์ subclassing์ ๋ํด ์๊ฐํด๋ณด์. MazeFactory์ subclass๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ, application์ ๋ฐ๋์ ์ฌ์ฉํ singleton์ ๊ฒฐ์ ํด์ผ ํ๋ค. ์ฌ๊ธฐ์๋ ํ๊ฒฝ๋ณ์๋ฅผ ํตํด maze์ ์ข
๋ฅ๋ฅผ ์ ํํ๊ณ , ํ๊ฒฝ๋ณ์๊ฐ์ ๊ธฐ๋ฐํ์ฌ ์ ํฉํ MazeFactory subclass๋ฅผ ์ธ์คํด์คํํ๋ ์ฝ๋๋ฅผ ๋ง๋ถ์ผ ๊ฒ์ด๋ค. Instance operation์ ์ด๋ฌํ ์ฝ๋๋ฅผ ๊ตฌํํ ์ข์ ์ฅ์์ด๋ค. ์๋ํ๋ฉด Instance operation์ MazeFactory๋ฅผ ์ธ์คํด์คํ๋ operation์ด๊ธฐ ๋๋ฌธ์ด๋ค.
~cpp MazeFactory* MazeFactory::Instance () { if (_instance == 0) { const char* mazeStyle = getenv ("MAZESTYLE"); if (strcmp (mazeStyle, "bombed") == 0) { _instance = new BombedMazeFactory; } else if (strcmp (mazeStyle, "enchanted") == 0) { _instance = new EnchantedMazeFactory; // ... other possible subclasses } else { // default _instance = new MazeFactory; } } return _instance; }์๋ก์ด MazeFactory์ subclass๋ฅผ ์ ์ํ ๋ ๋งค๋ฒ Instance ๊ฐ ๋ฐ๋์ ์์ ๋์ด์ผ ํ๋ค๋ ๊ฒ์ ์ฃผ๋ชฉํ์. ์ด application์์์ผ ๋ณ๋ค๋ฅธ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์๊ฒ ์ง๋ง, ์ด๋ฌํ ๊ตฌํ์ framework ๋ด์ ์ ์๋ abstract factory๋ค ๋ด์์๋ง ํ์ ๋์ด๋ฒ๋ฆฐ๋ค. (Implementation์ subclass ๊ด๋ จ ๋ถ๋ถ ์ฐธ์กฐ)
๊ฐ๋ฅํ ํด๊ฒฐ์ฑ
์ผ๋ก๋ Implementation์์ ์ธ๊ธํ registry approach๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค. Dynamic linking ๋ฐฉ๋ฒ๋ ๋ํ ์ ์ฉํ ๋ฐฉ๋ฒ์ด๋ค. Dynamic linking ์ application์ผ๋ก ํ์ฌ๊ธ ์ฌ์ฉํ์ง ์๋ subclass ๋ ์ ๋ถ loadํด์ผ ํ ํ์์ฑ์ ๋์ด์ค๋ค.
1.10. Known Uses ¶
Smalltalk-80Par90 ์ SingletonPattern์ ์๋ ChangeSet current๋ผ๋ ์ฝ๋์ ๋ํ change๋ค ์งํฉ๋ค์ด๋ค. ๋ ์ ํฉํ ์์ ๋ก๋ ํด๋์ค๋ค๊ณผ ๊ทธ๋ค์ metaclass ๊ฐ์ ๊ด๊ณ์ด๋ค. metaclass๋ ํด๋์ค์ ํด๋์ค๋ก, ๊ฐ metaclass๋ ํ๋์ ์ธ์คํด์ค๋ฅผ ๊ฐ์ง๋ค. metaclass๋ค์ ์ด๋ฆ์ ๊ฐ์ง์ง ์์ง๋ง (๊ทธ๋ค์ ๋จ์ผ์ธ์คํด์ค๋ฅผ ํตํ ๊ฐ์ ์ ์ธ ๋ฐฉ๋ฒ์ ใ
ใ
ํ๊ณ ), ๊ทธ๋ค์ ๋จ์ผ ์ธ์คํด์ค๋ฅผ ์ ์งํ๋ฉฐ ์ผ๋ฐ์ ์ผ๋ก ๋ค๋ฅธ ํด๋ผ์ด์ธํธ์ ์ํด ์์ฑ๋์ง ์๋๋ค.
InterViews user interface toolkitLCI+92๋ toolkit์ Session๊ณผ WidgetKit ํด๋์ค์ unique instance์ ์ ๊ทผํ์ง ์ํด SingletonPattern์ ์ด์ฉํ๋ค. Session์ application์ ๋ฉ์ธ ์ด๋ฒคํธ๋ฅผ dispatchํ๋ ๋ฃจํ๋ฅผ ์ ์ํ๊ณ ์ฌ์ฉ์ ์คํ์ผ๊ด๋ จ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ ์ฅํ๊ณ , ํ๋๋ ๊ทธ ์ด์์ ๋ฌผ๋ฆฌ์ display ์ ๋ํ ์ฐ๊ฒฐ๋ค(connections)์ ๊ด๋ฆฌํ๋ค. WidgetKit์ user interface widgets์ look and feel์ ์ ์ํ๋ค. WidgetKit::instance () operation์ Session ์์ ์ ์๋ ํ๊ฒฝ๋ณ์์ ๊ธฐ๋ฐํ์ฌ ํน์ WidgetKit ์ subclass๋ฅผ ๊ฒฐ์ ํ๋ค. Session์ ๋น์ทํ operation์ ์ง์ํ๋ display๊ฐ monochrome display์ธ์ง color display์ธ์ง ๊ฒฐ์ ํ๊ณ ์ด์ ๋ฐ๋ผ์ singleton ์ธ Session instance๋ฅผ ์ค์ ํ๋ค.
1.11. Related Patterns ¶
๋ง์ pattern๋ค์ด SingletonPattern์ ์ฌ์ฉํ์ฌ ๊ตฌํ๋ ์ ์๋ค. AbstractFactoryPattern, BuilderPattern, PrototypePattern์ ์ฐธ์กฐํ๋ผ.
์ง๋ฌธ
- ์ ๊ฐ ํ
์คํธ ์ฉ์ผ๋ก n-class singleton์ ๊ตฌํํ๋ ค ํฉ๋๋ค. ๊ทธ๋ฐ๋ฐ ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋๋ฐ ์ด๋ป๊ฒ ํด๊ฒฐํด์ผ ๋ ๊น์?
~cpp ----- CNSingleton.h ------ #include <afxtempl.h> class CNSingleton : public CObject { public: class CSingletonList; // C2248 ํด๊ฒฐ friend CSingletonList; // C2248 ํด๊ฒฐ static CNSingleton* Instance(); private: CNSingleton(); virtual ~CNSingleton(); //////////////////////////////////////////// // inner class static class CSingletonList : public CObject { public: CSingletonList() throw(); virtual ~CSingletonList() throw(); CNSingleton* Next(); private: void Init(); void Destory(); int m_Count; int m_Index; CList <CNSingleton*, CNSingleton*>* m_ContainerOfSingleton; }; static CSingletonList* m_Instances; }; ----- CNSingleton.cpp ------ #include "stdafx.h" #include "NSingleton.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CNSingleton::CSingletonList::CSingletonList() throw() { Init(); } CNSingleton::CSingletonList::~CSingletonList() throw() { Destory(); delete m_ContainerOfSingleton; } //////////////////////////////////////////////////////////////////////// // ๊ฐ์ฒด ์ด๊ธฐํ void CNSingleton::CSingletonList::Init() { m_Index = 0; m_Count = 3;//์์ m_ContainerOfSingleton = new CList <CNSingleton*, CNSingleton*>; for (int i = 0; i < m_Count; i++) { m_ContainerOfSingleton->AddTail(new CNSingleton()); } } //////////////////////////////////////////////////////////////////////// // ๊ฐ์ฒด destory void CNSingleton::CSingletonList::Destory() { POSITION position = m_ContainerOfSingleton->GetHeadPosition(); while(position) { delete m_ContainerOfSingleton->GetAt(position); m_ContainerOfSingleton->GetNext(position); } m_ContainerOfSingleton->RemoveAll(); } //////////////////////////////////////////////////////////////////////// // index์ ํด๋นํ๋ CNSingleton๋ฅผ Container์์ ์ฐพ์ ๋ฐํ CNSingleton* CNSingleton::CSingletonList::Next() { if (m_Index == m_ContainerOfSingleton->GetCount()) m_Index = 0; POSITION position = m_ContainerOfSingleton->FindIndex(m_Index); m_Index++; return m_ContainerOfSingleton->GetAt(position); } ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CNSingleton::CSingletonList* CNSingleton::m_Instances = NULL; CNSingleton::CNSingleton() { m_Instances = new CSingletonList(); } CNSingleton::~CNSingleton() { delete m_Instances; } //////////////////////////////////////////////////////////////////////// // n-th instance๋ฅผ ์ป์ด์จ๋ค. CNSingleton* CNSingleton::Instance() { return m_Instances->Next(); }
์ด ์์ค๋ฅผ ์ปดํ์ผํ๋ฉด, outer class์ ์์ฑ์๋ฅผ ํธ์ถํ๋ ๋ถ๋ถ, ์ฆ Init()๊ณผ Destroy()์์
error C2248: 'CNSingleton::CNSingleton' : cannot access private member declared in class 'CNSingleton' ๋ผ๊ณ ์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค.
error C2248: 'CNSingleton::CNSingleton' : cannot access private member declared in class 'CNSingleton' ๋ผ๊ณ ์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค.
inner class์์๋ outer class์ private ์์ฑ์์ ์ ๊ทผํ ๊ถํ์ด ์๋์?
๋ง์ฝ ์ ์ฝ๋๋ฅผ ์ ๋๋ก ์์ ํ๋ ค ํ๋ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ๋๋์? ์ฐธ๊ณ ๋ก ์ ๋ http://www.javaworld.com/javaworld/javaqa/2001-11/01-qa-1102-singleton.html์ ์๋ ์๋ฐ์์ค๋ฅผ cpp๋ก ํฌํ
ํ์ต๋๋ค. -- FredFrith