Post

⛓️ Java Design-Pattern Xβ…§ - Observer

⛓️ Java Design-Pattern Xβ…§ - Observer

πŸ“— γ€ŽJAVA μ–Έμ–΄λ‘œ λ°°μš°λŠ” λ””μžμΈ νŒ¨ν„΄ : μ‰½κ²Œ λ°°μš°λŠ” GoF의 23κ°€μ§€ λ””μžμΈ νŒ¨ν„΄γ€λ₯Ό 읽고 μ •λ¦¬ν•œ κΈ€μž…λ‹ˆλ‹€.

Observer νŒ¨ν„΄μ΄λž€?

  • κ΄€μ°° λŒ€μƒμ˜ μƒνƒœκ°€ λ³€ν™”ν•˜λ©΄ κ΄€μ°°μžμ—κ²Œ μ•Œλ¦°λ‹€.
  • μƒνƒœ 변화에 λ”°λ₯Έ 처리λ₯Ό κΈ°μˆ ν•  λ•Œ νš¨κ³Όμ μ΄λ‹€.

예제 ν”„λ‘œκ·Έλž¨

  • λ‹€μŒμ€ 수λ₯Ό 많이 μƒμ„±ν•˜λŠ” 객체λ₯Ό κ΄€μ°°μžκ°€ κ΄€μ°°ν•˜κ³  κ·Έ 값을 ν‘œμ‹œν•˜λŠ” ν”„λ‘œκ·Έλž¨μ΄λ‹€.
  • 단, ν‘œμ‹œν•˜λŠ” 방법은 κ΄€μ°°μžμ— 따라 λ‹€λ₯΄λ‹€.
  • κ°€λ Ή DigitObserverλŠ” 값을 숫자둜 ν‘œμ‹œν•˜μ§€λ§Œ, GraphObserverλŠ” 값을 κ°„λ‹¨ν•œ κ·Έλž˜ν”„λ‘œ ν‘œμ‹œν•œλ‹€.

ObserverΒ μΈν„°νŽ˜μ΄μŠ€

1
2
3
public interface Observer {
	public abstract void update(NumberGenerator generator);    
}
  • κ΄€μ°°μžλ₯Ό λ‚˜νƒ€λ‚΄λŠ” μΈν„°νŽ˜μ΄μŠ€λ‘œ, ꡬ체적인 κ΄€μ°°μžκ°€ 이 μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜κ²Œ λœλ‹€.
  • Java 클래슀 λΌμ΄λΈŒλŸ¬λ¦¬μ— λ“±μž₯ν•˜λŠ” java.util.Observerμ™€λŠ” λ‹€λ₯΄λ‹€.
  • update() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” 것은 NumberGenerator이닀.
  • NumberGeneratorκ°€ β€˜λ‚΄μš©μ΄ κ°±μ‹ λ˜μ—ˆμ–΄μš”. ν‘œμ‹œν•˜λŠ” μͺ½λ„ κ°±μ‹ ν•΄μ£Όμ„Έμš”.’라고 κ΄€μ°°μžμ— μ „λ‹¬ν•˜κΈ° μœ„ν•œ λ©”μ„œλ“œμ΄λ‹€.

NumberGenerator 클래슀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.ArrayList;
import java.util.List;

public abstract class NumberGenerator {
	// Observer μ €μž₯
	private List<Observer> observers = new ArrayList<>();
	
	// Observer μΆ”κ°€
	public void addObserver(Observer observer) {
		observers.add(observer);
	}
	
	// Observer에 톡지
	public void notifyObservers() {
		for (Observer o : observers) o.update(this);
	}
	
	// 수λ₯Ό 취득
	public abstract int getNumber();
	
	// 수λ₯Ό 생성
	public abstract void execute();
}
  • 수λ₯Ό μƒμ„±ν•˜λŠ” 좔상 ν΄λž˜μŠ€μ΄λ‹€.
  • μ‹€μ œλ‘œ 수λ₯Ό μƒμ„±ν•˜κ³  μ·¨λ“ν•˜λŠ” λ©”μ„œλ“œλŠ” ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ κ΅¬ν˜„ν•΄μ•Ό ν•˜λŠ” 좔상 λ©”μ„œλ“œλ‘œ κ΅¬μ„±λ˜μ–΄ μžˆλ‹€.
  • observers λŠ” NumberGeneratorλ₯Ό κ΄€μ°°ν•˜λŠ” Observerλ₯Ό μ €μž₯ν•˜λŠ” ν•„λ“œμ΄λ‹€.

RandomNumberGenerator 클래슀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.Random;

public class RandomNumberGenerator extends NumberGenerator {
	private Random random = new Random();
	private int number;
	
	// 수λ₯Ό 취득
	@Override
	public int getNumber() {
		return number;
	}
	
    // 수λ₯Ό 생성
	@Override
	public void execute() {
		for (int i = 0; i < 20; i++) {
			number = random.nextInt(50);
			notifyObservers();
		}
	}
}
  • NumberGenerator의 ν•˜μœ„ 클래슀둜 λ‚œμˆ˜λ₯Ό μƒμ„±ν•œλ‹€.
  • execute() λ©”μ„œλ“œλŠ” λ‚œμˆ˜λ₯Ό 20개 μƒμ„±ν•˜κ³ , κ·Έ λ•Œλ§ˆλ‹€ κ΄€μ°°μžμ—κ²Œ ν†΅μ§€ν•œλ‹€.

DigitObserver 클래슀

1
2
3
4
5
6
7
8
9
10
public class DigitObserver implements Observer {
	@Override
	public void update(NumberGenerator generator) {
		System.out.println("DigitObserver:" + generator.getNumber());
		
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) { }
	}
}
  • ꡬ체적인 κ΄€μ°°μž 클래슀둜, κ΄€μ°°ν•œ 수λ₯Ό 숫자둜 ν‘œμ‹œν•œλ‹€.

GraphObserver 클래슀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class GraphObserver implements Observer {
	@Override
	public void update(GraphObserver generator) {
		System.out.println("GraphObserver:");
		
		int count = generator.getNumber();
		for (int i = 0; i < count; i++) System.out.println("*");
		
		System.out.println("");
		
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) { }
	}
}
  • 이 ν΄λž˜μŠ€λŠ” κ΄€μ°°ν•œ 수λ₯Ό 간이 κ·Έλž˜ν”„λ‘œ ν‘œμ‹œν•œλ‹€.

Main 클래슀

1
2
3
4
5
6
7
8
9
10
11
12
public class Main {
	public static void main(String[] args) {
		NumberGenerator generator = new RandomNumberGenerator();
		Observer observer1 = new DigitObserver();
		Observer observer2 = new GraphObserver();
		
		generator.addObserver(observer1);
		generator.addObserver(observer2);
		
		generator.execute();
	}
}
  • 수 생성기와 κ΄€μ°°μžλ₯Ό 생성 및 등둝 ν•œ ν›„ generator.execute() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ 수λ₯Ό μƒμ„±ν•œλ‹€.

Observer νŒ¨ν„΄μ˜ λ“±μž₯인물

NumberGenerator 클래슀

  • κ΄€μ°°μžλ₯Ό 등둝 및 μ‚­μ œν•˜κ³  ν˜„μž¬ μƒνƒœλ₯Ό κ°€μ Έμ˜€λŠ” λ©”μ„œλ“œλ₯Ό κ°–κ³  있으며, κ΄€μ°° λŒ€μƒμž(Subject) 역을 λ§‘μ•˜λ‹€.

RandomNumberGenerator 클래슀

  • μƒνƒœκ°€ λ³€κ²½λ˜λ©΄ κ΄€μ°°μžμ—κ²Œ μ•Œλ¦¬λŠ” ꡬ체적인 κ΄€μ°° λŒ€μƒμž(ConcreteSubject) 역을 λ§‘μ•˜λ‹€.

Observer μΈν„°νŽ˜μ΄μŠ€

  • κ΄€μ°° λŒ€μƒμžλ‘œλΆ€ν„° β€˜μƒνƒœκ°€ λ³€ν™”ν–ˆμ–΄μš”β€™λΌκ³  전달 λ°›λŠ” κ΄€μ°°μž(Observer) 역할을 λ§‘μ•˜λ‹€.
  • 참고둜 전달받기 μœ„ν•œ λ©”μ„œλ“œκ°€ λ°”λ‘œ update()이닀.

DigitObserver, GraphObserver 클래슀

  • update() λ©”μ„œλ“œκ°€ 호좜되면 κ·Έ μ•ˆμ—μ„œ κ΄€μ°° λŒ€μƒμžμ˜ ν˜„μž¬ μƒνƒœλ₯Ό μ·¨λ“ν•˜λŠ” ꡬ체적인 κ΄€μ°°μž(ConcreteObserver) 역할을 λ§‘μ•˜λ‹€.

μ±…μ—μ„œ μ œμ‹œν•˜λŠ” 힌트

여기에도 κ΅ν™˜ κ°€λŠ₯성이 λ“±μž₯ν•œλ‹€.

  • λ””μžμΈ νŒ¨ν„΄μ˜ λͺ©μ  쀑 ν•˜λ‚˜λŠ” 클래슀λ₯Ό μž¬μ‚¬μš© κ°€λŠ₯ν•œ λΆ€ν’ˆμœΌλ‘œ λ§Œλ“œλŠ” 것이닀.
  • Observer νŒ¨ν„΄μ—μ„œλŠ” μƒνƒœλ₯Ό κ°€μ§„ ConcreteSubject와 μƒνƒœ λ³€ν™”λ₯Ό 톡보 λ°›λŠ” ConcreteObserverκ°€ μžˆλ‹€.
  • 그리고 κ·Έ λ‘˜μ„ μ—°κ²°ν•˜λŠ” 것이 μΈν„°νŽ˜μ΄μŠ€λ‘œμ„œμ˜ Subject와 Observerλ‹€.
  • κ°€λ Ή RandomNumberGeneratorλŠ” μžμ‹ μ„ κ΄€μ°°ν•˜λŠ” κ΄€μ°°μžκ°€ μ–΄λ–€ 클래슀의 μΈμŠ€ν„΄μŠ€μΈμ§€ λͺ¨λ₯Έλ‹€.
  • λ‹€λ§Œ observers ν•„λ“œμ— μ €μž₯된 μΈμŠ€ν„΄μŠ€κ°€ Observer μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜κ³ , update λ©”μ„œλ“œλ₯Ό κ°€μ§€κ³  μžˆλ‹€λŠ” 것 μ •λ„λŠ” μ•Œκ³  μžˆλ‹€.
  • DigitObserver 클래슀 λ˜ν•œ μžμ‹ μ΄ κ΄€μ°°ν•˜λŠ” λŒ€μƒμ΄ μ–΄λ–€ 클래슀의 μΈμŠ€ν„΄μŠ€μΈμ§€ μ‹ κ²½μ“°μ§€ μ•ŠλŠ”λ‹€.
  • λ‹€λ§Œ RandomNumberGenerator의 ν•˜μœ„ 클래슀이고, getNumber λ©”μ„œλ“œλ₯Ό κ°–κ³  μžˆλ‹€λŠ” 것은 μ•Œκ³  μžˆλ‹€.
  1. 좔상 ν΄λž˜μŠ€λ‚˜ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜μ—¬ ꡬ상 ν΄λž˜μŠ€λ‘œλΆ€ν„° 좔상 클래슀λ₯Ό λΆ„λ¦¬ν•œλ‹€.
  2. 인수둜 μΈμŠ€ν„΄μŠ€λ₯Ό 전달할 λ•Œλ‚˜ ν•„λ“œλ‘œ μΈμŠ€ν„΄μŠ€λ₯Ό μ €μž₯ν•  λ•ŒλŠ” ꡬ상 ν΄λž˜μŠ€ν˜•μœΌλ‘œ ν•˜μ§€ μ•Šκ³  좔상 ν΄λž˜μŠ€λ‚˜ μΈν„°νŽ˜μ΄μŠ€ν˜•μœΌλ‘œ ν•΄ λ‘”λ‹€.
  • μœ„ μ „μ œλ₯Ό μ§€ν‚€λŠ” ν•œ ꡬ상 클래슀 뢀뢄을 μ‰½κ²Œ κ΅ν™˜ν•  수 μžˆλ‹€.

Observer의 μˆœμ„œ

  • Subject μ—­μ—λŠ” μ—¬λŸ¬ Observerκ°€ λ“±λ‘λ˜μ–΄ μžˆλŠ”λ°, 일반적으둜 ConcreteObserver μ—­μ˜ 클래슀λ₯Ό 섀계할 λ•ŒλŠ” update() λ©”μ„œλ“œκ°€ ν˜ΈμΆœλ˜λŠ” μˆœμ„œκ°€ λ°”λ€Œμ–΄λ„ λ¬Έμ œκ°€ 생기지 μ•Šλ„λ‘ ν•΄μ•Ό ν•œλ‹€.
  • μ• μ΄ˆμ— 각 클래슀의 독립성이 μ œλŒ€λ‘œ μœ μ§€λ˜λ©΄, μ˜μ‘΄μ„±μ˜ ν˜Όλž€μ€ μΌμ–΄λ‚˜μ§€ μ•ŠλŠ”λ‹€.

Observer의 ν–‰μœ„κ°€ Subject에 영ν–₯을 λ―ΈμΉ  λ•Œ

  • Observer νŒ¨ν„΄μ—μ„œλŠ” Subjectκ°€ update() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” 계기가 λ‹€λ₯Έ ν΄λž˜μŠ€λ‘œλΆ€ν„° μ˜€κΈ°λ„ ν•œλ‹€.
  • 예λ₯Ό λ“€μ–΄ GUIμ—μ„œ μ‚¬μš©μžκ°€ λ²„νŠΌμ„ λˆ„λ₯΄λŠ” 이벀트λ₯Ό κ³„κΈ°λ‘œ update() λ©”μ„œλ“œκ°€ ν˜ΈμΆœλ˜λŠ” κ²½μš°κ°€ 자주 μžˆλ‹€.
  • λ™μ‹œμ— Subjectκ°€ update() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” 계기가 ν•΄λ‹Ή Observer인 κ²½μš°λ„ μžˆλŠ”λ°, 이런 경우 μ‘°μ‹¬ν•΄μ„œ μ„€κ³„ν•˜μ§€ μ•ŠμœΌλ©΄ λ©”μ„œλ“œ 호좜이 μ˜μ›νžˆ 반볡될 수 μžˆλ‹€.
  • Subject μƒνƒœ λ³€ν™” β†’ Observer둜 톡지 Observerκ°€ Subject의 λ©”μ„œλ“œ 호좜 β†’ Subject μƒνƒœ λ³€ν™” β†’ ...
  • κ·Έλ ‡κΈ° λ•Œλ¬Έμ— ν˜„μž¬ 톡지 처리 쀑인지λ₯Ό Observerκ°€ νŒλ‹¨ν•˜κ±°λ‚˜, ν†΅μ§€ν•˜λŠ” 타이밍을 Subjectκ°€ κ³ λ €ν•˜λŠ” λ“±μ˜ λŒ€μ±…μ΄ ν•„μš”ν•˜λ‹€.

갱신을 μœ„ν•œ 힌트 정보 닀루기

  • RandomNumberGeneratorλŠ” update() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ β€˜κ°±μ‹ λμ–΄μš”β€™λΌκ³  Observerμ—κ²Œ ν†΅μ§€ν•œλ‹€.
  • update() λ©”μ„œλ“œμ˜ 인수둜 μ£Όμ–΄μ§€λŠ” 것은 RandomNumberGenerator μΈμŠ€ν„΄μŠ€ 뿐이기 λ•Œλ¬Έμ—, ObserverλŠ” getNumber() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜μ—¬ ν•„μš”λ‘œ ν•˜λŠ” 값을 μ–»μ–΄μ•Ό ν•œλ‹€.
  • 상황에 따라 λ‹€μŒκ³Ό 같이 μ μ ˆν•˜κ²Œ 힌트 정보λ₯Ό λ„˜κΈΈ 수 μžˆλ‹€.
  1. void update(NumberGenerator generator); ... (ν˜„ν–‰)
  2. void update(NumberGenerator generator, int number); ... (2)
  3. void update(int number); ... (3)
  • (2)λΆ€ν„°λŠ” Subject에 더해 힌트 정보λ₯Ό λ„˜κ²¨ μ€€λ‹€.
  • 이둜써 ObserverλŠ” Subjectλ‘œλΆ€ν„° 정보λ₯Ό μ–»μ–΄ μ˜€λŠ” 수고λ₯Ό 덜 수 μžˆλ‹€.
  • λ‹€λ§Œ μ΄λŸ¬ν•œ 힌트 정보λ₯Ό μ€€λ‹€λŠ” 것은 Subjectκ°€ Observer의 처리 λ‚΄μš©μ„ μ˜μ‹ν•˜κ³  μžˆλ‹€λŠ” 것이닀.
  • μ–΄λŠ μ •λ„μ˜ 힌트 정보λ₯Ό 전달할 κ²ƒμΈμ§€λŠ” ν”„λ‘œκ·Έλž¨μ˜ λ³΅μž‘μ„±μ„ 잘 κ³ λ €ν•΄μ„œ νŒλ‹¨ν•΄μ•Ό ν•œλ‹€.
  • (3)의 경우 ν•˜λ‚˜μ˜ Observerκ°€ μ—¬λŸ¬ Subjectλ₯Ό κ΄€μ°°ν•˜λŠ” κ²½μš°μ—λŠ” λ„˜μ–΄μ˜¨ μˆ«μžκ°€ μ–΄λŠ Subject의 정보인지 λͺ¨λ₯΄κΈ° λ•Œλ¬Έμ— λΆ€μ μ ˆν•˜λ‹€.

κ΄€μ°°ν•˜κΈ°λ³΄λ‹€ 전달 λ°›κΈ°λ₯Ό κΈ°λ‹€λ¦°λ‹€.

  • κ΄€μ°°μžκ°€ λŠ₯λ™μ μœΌλ‘œ κ΄€μ°°ν•˜λŠ” 것이 μ•„λ‹ˆλΌ, κ΄€μ°° λŒ€μƒμžμ˜ 톡보λ₯Ό μˆ˜λ™μ μœΌλ‘œ κΈ°λ‹€λ¦°λ‹€λŠ” μ μ—μ„œ Publish-Subscribe νŒ¨ν„΄μœΌλ‘œ λΆˆλ¦¬κΈ°λ„ ν•œλ‹€.
  • publish와 subscribeλΌλŠ” ν‘œν˜„μ΄ 더 싀체에 λ§žμ„μ§€λ„ λͺ¨λ₯Έλ‹€.

Model / View / Controller(MVC)

  • MVC κ΅¬μ‘°μ—μ„œ Modelκ³Ό View의 κ΄€κ³„λŠ” Observer νŒ¨ν„΄μ˜ Subject와 Observer 관계에 λŒ€μ‘ν•œλ‹€.
  • Model의 경우 ν‘œμ‹œ ν˜•μ‹μ— μ˜μ‘΄ν•˜μ§€ μ•ŠλŠ” λ‚΄λΆ€ λͺ¨λΈμ„ μ‘°μž‘ν•œλ‹€λŠ” μ μ—μ„œ, View의 경우 μ–΄λ–»κ²Œ 보여 쀄지 κ΄€λ¦¬ν•˜λŠ” μ μ—μ„œ κ·ΈλŸ¬ν•˜λ‹€.
  • 일반적으둜 ν•˜λ‚˜μ˜ Model에 μ—¬λŸ¬ Viewκ°€ λŒ€μ‘ν•œλ‹€.
This post is licensed under CC BY 4.0 by the author.