U E D R , A S I H C RSS

Gof/Singleton


1. Singleton

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 μžμ‹ μ˜ μœ μΌν•œ μΈμŠ€ν„΄μŠ€λΌ μƒμ„±ν•˜λŠ” μ±…μž„μ„ 가진닀.

1.6. Collaborations

  • ν΄λΌμ΄μ–ΈνŠΈλŠ” 였직 Singleton의 Instance operation으둜만 Singleton μΈμŠ€ν„΄μŠ€μ— μ ‘κ·Όν•  수 μžˆλ‹€.

1.7. Consequences

SingletonPattern은 μ—¬λŸ¬κ°€μ§€ μž₯점을 가진닀.
  1. ν΄λž˜μŠ€μ— λŒ€ν•œ 접근이 였직 ν•˜λ‚˜μ˜ μΈμŠ€ν„΄μŠ€μ—κ²Œλ‘œ μ œν•œλœλ‹€. Singleton ν΄λž˜μŠ€λŠ” 자기 μžμ‹ μ˜ 단일 μΈμŠ€ν„΄μŠ€λΌ μΊ‘μŠν™”ν•˜κΈ° λ•Œλ¬Έμ—, ν΄λΌμ΄μ–ΈνŠΈκ°€ μ–Έμ œ, μ–΄λ–»κ²Œ μ ‘κ·Όν•˜λ˜μ§€ κ·Έ 접근이 μ—„κ²©ν•˜κ²Œ μ œμ–΄λœλ‹€.
  2. namespaceλΌ μ„인닀. SingletonPattern은 global variable을 μ„μž„μœΌλ‘œμ„œ global variable둜 μΈν•œ namespace의 λ‚­λΉ„λΌ μ„인닀.
  3. λͺ…령어와 ν‘œν˜„μ„ ν™•μž₯μ‹œν‚¬ 수 μžˆλ‹€. Singleton classλŠ” subclass될 수 있고, 이 ν™•μž₯된 클래슀의 μΈμŠ€ν„΄μŠ€λΌ κ°€μ§€κ³  μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ„μ •ν•˜λŠ” 것은 쉽닀. run-time쀑에 ν•„μš”ν•œ κ²½μš°μ—λ„ κ°€λŠ₯ν•˜λ‹€.
  4. μ—¬λŸ¬κ°œμ˜ μΈμŠ€ν„΄μŠ€λΌ ν—ˆμš©ν•œλ‹€. ν”„λ‘œκ·Έλž˜λ¨Έμ˜ λ§ˆμŒμ— 따라 μ‰½κ²Œ Singleton class의 μΈμŠ€ν„΄μŠ€λΌ ν•˜λ‚˜μ΄μƒμ„ λ‘˜ μˆ˜λ„ μžˆλ„λ‘ ν•  수 μžˆλ‹€. κ²Œλ‹€κ°€ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ μ‚¬μš©ν•˜λŠ” μΈμŠ€ν„΄μŠ€λ“€μ„ μ œμ–΄ν•˜κΈ° μœ„ν•΄ λ™μΌν•œ 접근방법을 μ·¨ν•  수 μžˆλ‹€. 단지 Singleton μΈμŠ€ν„΄μŠ€μ— μ ‘κ·Όν•˜λŠ” 것을 보μž₯ν•˜λŠ” operation만 μˆ˜μ •ν•˜λ©΄ λœλ‹€.
  5. 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 λ“€ κ°„μ—λŠ” μ–΄λ– ν•œ μ˜μ‘΄μ„±λ„ μ‘΄μž¬ν•  수 μ—†μŒμ„ 의λΈν•œλ‹€. 만일 그럴 수 μžˆλ‹€λ©΄, μ—λŸ¬λΌ ν”Όν•  수 μ—†λ‹€.
μ•½κ°„ 첨언을 ν•˜λ©΄, global/static 객체의 접근은 singleton듀이 μ‚¬μš©λ˜κ±΄ μ‚¬μš©λ˜μ§€ μ•Šκ±΄ 간에 λͺ¨λ“  singleton이 λ§Œλ“€μ–΄μ§€λ„λ‘ ν•œλ‹€λŠ” 것이닀. static member function λΌ μ‚¬μš©ν•¨μœΌλ‘œμ„œ μ΄λŸ¬ν•œ λͺ¨λ“  λ¬Έμ œλ“€μ„ ν”Όν•  수 μžˆλ‹€.

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' 라고 μ—λŸ¬κ°€ λ°œμƒν•©λ‹ˆλ‹€.
inner classμ—μ„œλŠ” outer class의 private μƒμ„±μžμ— μ ‘κ·Όν•  κΆŒν•œμ΄ μ—†λ‚˜μš”?
λ§Œμ•½ μ € μ½”λ“œλΌ μ œλŒ€λ‘œ μˆ˜μ •ν•˜λ € ν•œλ‹€λ©΄ μ–΄λ–»κ²Œ ν•΄μ•Ό λ˜λ‚˜μš”? 참고둜 μ €λŠ” http://www.javaworld.com/javaworld/javaqa/2001-11/01-qa-1102-singleton.html에 μžˆλŠ” μžλ°”μ†ŒμŠ€λΌ cpp둜 ν¬νŒ…ν–ˆμŠ΅λ‹ˆλ‹€. -- FredFrith

μ œκ°€ μΆ”κ°€ν•œ λ‹€μŒ 두μ„
~cpp 
         class CSingletonList; //  C2248 ν•΄κ²°
         friend CSingletonList; //  C2248 ν•΄κ²° 
을 λ³΄μ‹­μ‹œμ˜€. μ΄λ ‡κ²Œ ν•˜λ©΄ λ©λ‹ˆλ‹€. -- imays
DeleteMe) imays 이면, ν˜Ήμ‹œ ν˜„μ§μ΄ν˜•μ΄μ‹ κ°€μš”? --기얡을 ν•˜μ‹€μ§€ λͺ¨λ₯΄κ² λŠ” 1002 -- λ„΅ imays
Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:23:19
Processing time 0.0565 sec