Observer Pattern
Head First Design Pattern
ν κ°μ²΄μ μνκ° λ°λλ©΄ κ·Έ κ°μ²΄μ μμ‘΄νλ λ€λ₯Έ κ°μ²΄λ€μκ² μ λ³΄κ° μλμΌλ‘ κ°±μ λλ λ°©μμΌλ‘, μΌλλ€(one-to-many) μμ‘΄μ±μ μ μν©λλ€.
μ΅μ λ² ν¨ν΄μ κ΄μ°°μ ν¨ν΄μ΄λΌκ³ λ ν©λλ€.
μΌλλ€ κ΄κ³λ₯Ό μ΄λ£¨κ³ μμΌλ©°, μνκ° μ
λ°μ΄νΈλλ©΄ λͺ¨λ μ΅μ λ²λ€μκ² μ 보λ₯Ό κ°±μ ν μ μλλ‘ νλ κ²μ μλ―Έν©λλ€
μμ ) μ νλΈ κ΅¬λ μλ
μ² μ(Observer)κ° μ½λ© 곡λΆλ₯Ό μν΄ μ νλΈμμ νλ‘κ·Έλλ° κ΄λ ¨ μμμ μ°Ύκ³ μμ΅λλ€.
κ·Έλ°λ° Luckygg(Subject)λΌλ μ¬λμ μ±λμ μ’μ μμλ€μ΄ μλ κ²μ μκ² λμ΅λλ€.
νλ λ κ°μ λ μμλ€μ λ³΄κ² λλ€κ° μ΄λμ λͺ¨λ μμλ€μ λ³΄κ² λμ΅λλ€.
μ΄μ μλ‘μ΄ μμμ΄ μ
λ°μ΄νΈλλ κ²μ κΈ°λ€λ¦¬κ³ μμ΅λλ€. κ·Έλ°λ° μ΄ μμμ΄ μΈμ μ¬λΌμ¬ μ€ μκ³ λ§λ₯ κΈ°λ€λ¦΄κΉμ?
μ΄λ, μ±λ ꡬλ
(Register)μ νμ¬ μ
λ°μ΄νΈ μλ¦Ό(Notify)μ λ°κ² νλ λ°©λ²μ΄ μμ΅λλ€.
μ νλΈ μ±λ κ΄λ¦¬μκ° μμμ μ
λ°μ΄νΈνλ©΄, ꡬλ
νκ³ μλ λͺ¨λ μ¬μ©μλ€μκ² μλ¦Όμ μ λ¬νλ κ²μ
λλ€.
νΉμ μ 보λ₯Ό μ¬λ¬ λ·°μμ λμμ μ»κΈ° μν΄
μ£Όμ μ(Subject)μ ꡬλ
μ(Observer)λ₯Ό λ±λ‘(Register)νμ¬ μ 보λ₯Ό λ°λ(κ°±μ , Notify) κ²μ μ΅μ λ² ν¨ν΄(Observer pattern)μ΄λΌκ³ ν©λλ€.
λ¬Όλ‘ λ±λ‘μ νμΌλ ν΄μ§(Remove)λ κ°λ₯ν©λλ€.
μ΅μ λ² ν¨ν΄μμ μ£Όμ μλ μ΅μ λ²μ λν μ λ³΄κ° μμ΅λλ€. μ€μ§ μ΅μ λ²κ° νΉμ μΈν°νμ΄μ€(Interface)
λ₯Ό ꡬν
νλ€λ κ² λ§ μκ³ μμ΅λλ€. μ¦, μ΅μ λ²κ° λ¬΄μ¨ λμμ νλμ§ λͺ¨λ₯Έλ€λ
κ²μ
λλ€. κ²λ€κ° μ΅μ λ²λ μΈμ λ μ§ μλ‘ μΆκ°λκ±°λ μ κ±°
λ μ μμΌλ©° μλ‘μ΄ νμμ μ΅μ λ²λ₯Ό μΆκ°ν λμλ μ£Όμ μ μ ν μν₯μ μ£Όμ§ μμ΅λλ€
. μ΄λ¬ν κ΄κ³λ₯Ό λμ¨ν κ²°ν©(Loose coupling)
μ΄λΌκ³ ν©λλ€.
γ
Subject interface
λ λ±λ‘
, ν΄μ
, κ°±μ
μ μν APIλ₯Ό μ 곡ν©λλ€.
κ·Έλ¦¬κ³ μ΄λ₯Ό μμλ°λ concrete Subject Class
λ λ±λ‘
, ν΄μ
, κ°±μ
μ ꡬννκ³ κΈ°ν ν¨μλ ꡬνν μ μμ΅λλ€
.
Observer interfaceλ Subjectμμ κ°±μ ν λ νΈμΆλλ update APIλ§ μ 곡ν©λλ€.
λ§μ§λ§μΌλ‘ Observer interfaceλ₯Ό μμλ°λ A, B, C Classμ updateλ₯Ό ꡬνν©λλ€. μ΄κ²μ΄ μ΅μ λ² ν¨ν΄μ κ°μ₯ κΈ°λ³Έμ μΈ κ΅¬μ‘°μ
λλ€.
γ
γ
μ½λ μμ
Concrete Subject classμμ κ°μ λ³κ²½νλ©΄ λ±λ‘λ λͺ¨λ Observerλ€μκ² κ°±μ νλ κ°λ¨ν ꡬ쑰μ λλ€.
γ
γ
Subject interface
μ
λλ€. Observerλ₯Ό λ±λ‘, ν΄μ , κ°±μ νκΈ° μν APIλ₯Ό λνλ
λλ€.
public interface ISubject {
//λ±λ‘
void registerObserver(IObserver observer);
//ν΄μ
void removeObserver(IObserver observer);
//κ°±μ
void notifyObserver();
}
Observer interface
μ
λλ€.
public interface IObserver {
void update();
}
ConcreteSubjectλ
Subject interfaceλ₯Ό μμλ°μ΅λλ€. κ·Έλ¦¬κ³ ArrayListλ₯Ό μ¬μ©νμ¬ observer μ 보λ₯Ό κ°μ§κ³ μμ΅λλ€.
public class ConcreteSubject implements ISubject {
private List<IObserver> observers;
public ConcreteSubject() {
observers = new ArrayList<IObserver>();
}
@Override
public void registerObserver(IObserver observer) {
observers.add(observer);
}
@Override
public void removeObserver(IObserver observer) {
observers.remove(observers.indexOf(observer));
}
@Override
public void notifyObserver() {
observers.stream().forEach(observer -> {
observer.update();
});
}
}
μλλ κ° Observer interfaceλ₯Ό μμλ°λ A, B, C classμ λλ€. λκ°μ ν΄λμ€κ° μ€λ³΅λ κ²μ λλ€. κ° ν΄λμ€ μμ±μμμ ConcreteSubjectλ₯Ό μΈμλ‘ λ°κ³ , registerObserverλ₯Ό νΈμΆνμ¬ μμ μ μ΅μ λ²λ‘μ λ±λ‘ν©λλ€.
public class AClazz implements IObserver {
private String name;
public AClazz(String name) {
this.name = name;
}
@Override
public void update() {
System.out.println(this.name + " μ
λ°μ΄νΈ");
}
}
public class BClazz implements IObserver{
private String name;
public BClazz(String name) {
this.name = name;
}
@Override
public void update() {
System.out.println(this.name + " μ
λ°μ΄νΈ");
}
}
public class CClazz implements IObserver{
private String name;
public CClazz(String name) {
this.name = name;
}
@Override
public void update() {
System.out.println(this.name + " μ
λ°μ΄νΈ");
}
}
μ΄μ λ©μΈ νλ‘κ·Έλ¨ μ λλ€. ConcreteSubject λ° A, B, C μΈμ€ν΄μ€λ₯Ό μμ±νλλ° A, B, C κ° μΈμ€ν΄μ€κ° μ΅μ λ²λ‘μ ConcreteSubject μΈμ€ν΄μ€μ λ±λ‘λ©λλ€. λ§μ§λ§ μ€μΈ setValue(10)μ νΈμΆνλ©΄ λͺ¨λ μ΅μ λ²μ updateκ° νΈμΆλ©λλ€.
import dp.update.*;
public class Main {
public static void main(String[] args) {
ISubject subject = new ConcreteSubject();
AClazz a = new AClazz("A ꡬλ
μ");
BClazz b = new BClazz("B ꡬλ
μ");
CClazz c = new CClazz("C ꡬλ
μ");
subject.registerObserver(a);
subject.registerObserver(b);
subject.registerObserver(c);
System.out.println("1μ°¨ μ
λ°μ΄νΈ");
subject.notifyObserver(); // a, b, c ꡬλ
μ μ
λ°μ΄νΈ
System.out.println("--------------------");
System.out.println("C ꡬλ
μ μ κ±°");
subject.removeObserver(c); // c ꡬλ
μ μ κ±°
System.out.println("--------------------");
System.out.println("2μ°¨ μ
λ°μ΄νΈ");
subject.notifyObserver(); // a, b ꡬλ
μ μ
λ°μ΄νΈ
System.out.println("--------------------");
}
}
1μ°¨ μ
λ°μ΄νΈ
A ꡬλ
μ μ
λ°μ΄νΈ
B ꡬλ
μ μ
λ°μ΄νΈ
C ꡬλ
μ μ
λ°μ΄νΈ
--------------------
C ꡬλ
μ μ κ±°
--------------------
2μ°¨ μ
λ°μ΄νΈ
A ꡬλ
μ μ
λ°μ΄νΈ
B ꡬλ
μ μ
λ°μ΄νΈ
--------------------