Observer ํŒจํ„ด, ๋งŽ์ด ๋“ค์–ด๋ดค๋‹ค. GoF์˜ ์ •์˜๋กœ ์•Œ์•„๋ณด์ž.

Observer

  • ๊ด€์ฐฐ์ž, ๊ฐ์‹œ์ž
  • ๋ณ€ํ™”๊ฐ€ ์ƒ๊ธฐ๋ฉด ์•Œ์•„์ฑˆ๋‹ค.
  • ๋‹ค๋งŒ ์ด ๊ด€์ฐฐ์ž๋Š” ์—ฌ๋Ÿฌ๋ช…์ผ ์ˆ˜ ์žˆ๋‹ค.

pub-sub Pattern

  • Observer๋ณด๋‹ค ๋งŽ์ด ์“ฐ์ด๋Š” ํŒจํ„ด
  • ๋ฐœํ–‰-๊ตฌ๋… ํŒจํ„ด
  • ๋น„์Šทํ•˜๋‚˜ ์—„๋ฐ€ํžˆ ๋งํ•˜๋ฉด ๋‹ค๋ฅธ ํŒจํ„ด์ด๋‹ค.
  • ํ•˜์ง€๋งŒ ์ด๋ฃจ๋ ค๋Š” ๋ชฉ์ ์€ ๋น„์Šทํ•˜์—ฌ ๊ฐ™์€ ํŒจํ„ด์ด๋ผ ๋ณด๋Š” ์ผ๋„ ๋งŽ๋‹ค.
  • pub-sub์ด ๋ณด๋‹ค ์ผ๋ฐ˜์ ์ธ (observer์˜ ์ƒ์œ„ ์ง‘ํ•ฉ) ๊ฐœ๋…์ด๋ผ ์ƒ๊ฐ

LogManager

  • ๋ฐ”๋กœ ์ „์— ๋ดค๋˜ LogManager๊ฐ€ ๊ทธ ํŒจํ„ด
  • program์ด LogManager์—๊ฒŒ ๋กœ๊ทธ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๊ณ ,
  • LogManager๋Š” ๊ตฌ๋…์ž(ConsoleLogger, EmailLogger)๋“ค์—๊ฒŒ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋ƒ„

Observer Pattern์˜ ์˜ˆ

  • ํฌ๋ผ์šฐ๋“œํŽ€๋”ฉ
  • ๋ˆ์ด ๋“ค์–ด์˜ฌ ๋•Œ๋งˆ๋‹ค ๋‘ ๊ฐœ์ฒด๋ฅผ ์—…๋ฐ์ดํŠธํ•  ๊ฒƒ์ž„
    • ์žฅ๋ถ€ (๊ธˆ์•ก)
    • ํฐ์—์„œ ํ‘ธ์‹œ ๋…ธํ‹ฐ (์ด๋ฆ„, ๊ธˆ์•ก)
      • ์‹ค์ œ๋กœ ํ‘ธ์‹œ ์•Œ๋ฆผ์ด pub-sub ํŒจํ„ด์ž„
      • ์ด๋ฅผ ์ด๋ฒคํŠธ ์ฃผ๋„ ์•„ํ‚คํ…์ฒ˜๋ผ๊ณ ๋„ ํ•œ๋‹ค.
        • ์ด๋ฒคํŠธ๊ฐ€ ์ผ์–ด๋‚˜๋ฉด ์•Œ๋ ค์คŒ

IFundingCallback

public interface IFundingCallback {
    void onMoneyRaised(String backer, int amount);
}
  • ๋™์ผํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋ฐ›๊ธฐ ์œ„ํ•ด ๋งŒ๋“ฆ

BookkeepingApp

public final class BookkeepingApp implements IFundingCallback {
 
    // ... ์ƒ๋žต
 
    @Override
    public void onMoneyRaised(String backer, int amount) {
        // ์žฅ๋ถ€์— ์ƒˆ ๋‚ด์—ญ ์ถ”๊ฐ€
        // amount๋งŒ ์‚ฌ์šฉ
    }
}

MobileApp

public final class MobileApp implements IFundingCallback {
 
    @Override
    public void onMoneyRaised(String backer, int amount) {
        // ๋ชจ๋ฐ”์ผ ์•ฑ์— ์•Œ๋ฆผ ๋ณด์—ฌ์คŒ
        // amount, backer ๋‘˜๋‹ค ์‚ฌ์šฉ
    }
}

CrowdFundingAccount

public final class CrowdFundingAccount {
    private int balance;
 
    private ArrayList<IFundingCallback> subscribers;
 
    public CrowdFundingAccount() {
        this.subscrivers = new ArrayList<IFundingCallback>();
    }
 
    public void subscribe(IFundingCallBack sub) {
        subscrivers.add(sub);
    }
 
    public void support(String backer, int amound) {
        this.balance += amount;
 
        for (IFundingCallback sub : subscribers) {
            sub.onMoneyRaised(backer, amount);
        }
    }
}

pub-sub๊ณผ์˜ ์ฐจ์ด

  • ๋‹ค๋Œ€๋‹ค์ธ ๊ด€๊ณ„๋ผ๋ฉด pub-sub์ด๋ผ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ง€๊ธˆ ์œ„์˜ ๊ฒฝ์šฐ ๋ฐœํ–‰์ž๊ฐ€ ํ•˜๋‚˜๋‹ค.
  • ๊ทธ๋Ÿฐ๋ฐ ๋งŒ์•ฝ ๋ฐœํ–‰์ž๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ๊ฐ€ ๋  ์ˆ˜ ์žˆ๊ณ , ๊ทธ๊ฑธ ๋ฐ›๋Š” ์ชฝ๋„ ์—ฌ๋Ÿฌ๊ฐœ๋ผ๊ณ  ํ•ด๋ณด์ž.
  • ์ด๋Ÿด ๊ฒฝ์šฐ ๊ทธ ์ค‘๊ฐ„์— ์กฐ์œจํ•ด์ฃผ๋Š” ๊ฐœ์ฒด๊ฐ€ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
  • ๊ทธ ์ฐจ์ด๊ฐ€ ์ „๋ถ€๋‹ค. ์œ„๊ฐ™์€ ๊ฒฝ์šฐ๋Š” Account์— ์ง์ ‘์ ์œผ๋กœ ๋นจ๋Œ€๋ฅผ ๊ฝ‚๊ณ  ์žˆ๋Š” ํ˜•ํƒœ๋‹ˆ Observer์ด๋‹ค.
  • pub-sub์ด๋ผ๋ฉด, support()๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด, ์ค‘๊ฐ„ ๊ด€๋ฆฌ ๊ฐœ์ฒด์— ์š”์ฒญํ•˜๊ณ , ๊ทธ ๊ฐœ์ฒด๊ฐ€ ๊ตฌ๋…์ž๋“ค์—๊ฒŒ ๋‹ค์‹œ ์•Œ๋ฆผ์„ ์ฃผ๋Š” ํ˜•ํƒœ๊ฐ€ ๋  ๊ฒƒ์ด๋‹ค.
    • iOS์˜ NotificationCenter์™€ ๊ฐ™์€ ๋ฐฉ์‹์ด๋‹ค.

Observer Pattern๊ณผ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฌธ์ œ

  • Observer Pattern์€ ๊ฒฐ๊ตญ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ๋ชฉ๋ก์ด๋‹ค.
  • ๊ทธ๋Ÿฐ๋ฐ ์ด๋Ÿฐ ๋ฐฉ์‹์€ Managed ์–ธ์–ด์—์„œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๋งŒ๋“œ๋Š” ์ฃผ๋ฒ”์ด๋‹ค.
    • ๋ฉ”๋ชจ๋ฆฌ ์ง์ ‘ ๊ด€๋ฆฌ
    • ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ ๊ธฐ๋ฐ˜ ์–ธ์–ด
      • ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ์•ˆ์ƒ๊ธฐ๋Š”๊ฒŒ ์•„๋‹˜
      • ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋‹ค๋ฅธ ๊ฒƒ
CrowdFundingAccount funding;
 
BookkeepingApp book = new BookkeepingApp();
funding.subscribe(book);
 
// ์žฅ๋ถ€ ์•ฑ์œผ๋กœ ๋ฌด์–ธ๊ฐ€ ์ฒ˜๋ฆฌ
 
// ๋‹คํ•จ, ์ด์ œ ๊ฐœ์ฒด ์ง€์šฐ์ž.
 
book = null;
 
// ์‹œ๊ฐ„์ด ๋งŽ์ด ์ง€๋‚จ - ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ ํ•œ๋ฒˆ ๋Ž
// ํ•˜์ง€๋งŒ ์•ˆ์ง€์›Œ์ง ์‘? ์™œ?
  • funding ๊ฐœ์ฒด๊ฐ€ ํ•ด๋‹น ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ์žก๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์‚ฌ์šฉ์ค‘์ด๋ผ๊ณ  ์ƒ๊ฐํ•จ
    • subscribers
  • ๋ช…์‹œ์ ์œผ๋กœ unsubscribe()์™€ ๊ฐ™์€ ๋™์ž‘์œผ๋กœ ๋ฐฐ์—ด์—์„œ ๋นผ์ค˜์•ผ ํ•จ
public void unsubscribe(IFundingCallback sub) {
    subscribers.remove(sub);
}
  • ์ด๊ฑฐ ์•ˆ๊นŒ๋จน์„ ์ž์‹  ์žˆ์Œ?โ€ฆ
  • ์—ฌ๊ธฐ์„œ ์ฐพ๊ธฐ๋„ ๊ต‰์žฅํžˆ ์–ด๋ ต๋‹ค..
  • Java์˜ ๊ฒฝ์šฐ์—๋Š” book์ด ์ง€์›Œ์งˆ ๋•Œ ์ž๋™์œผ๋กœ unsubscribe()๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ๋„ ์–ด๋ ต๋‹ค.
    • C++์—๋Š” destructor๋ฅผ ํ†ตํ•ด ์ž๋™ํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.
    • Swift deinit()
  • ๋˜ C++์€ ๊ตณ์ด heap์— ์•ˆ๋งŒ๋“ค๊ณ  stack์— ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ๋‹ค.
    • ์ด๋ ‡๊ฒŒ ๋˜๋ฉด ํ•จ์ˆ˜ ์Šค์ฝ”ํ”„ ๋ฒ—์–ด๋‚˜๋ฉด ๋ฌด์กฐ๊ฑด์ ์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น ํ•ด์ œ ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.
      • stack์ด ๊ทธ๋ ‡๊ฒŒ ๋„๋‹ˆ๊นŒ!

Reference