Skip to content

Latest commit

Β 

History

History
236 lines (162 loc) Β· 7.34 KB

File metadata and controls

236 lines (162 loc) Β· 7.34 KB

2μž₯. μ˜΅μ €λ²„ νŒ¨ν„΄

observer-uml

ν•œ 객체의 μƒνƒœκ°€ λ°”λ€Œλ©΄ κ·Έ 객체에 μ˜μ‘΄ν•˜λŠ” λ‹€λ₯Έ κ°μ²΄μ—κ²Œ 연락이 κ°€κ³  μžλ™μœΌλ‘œ λ‚΄μš©μ΄ κ°±μ‹ λ˜λŠ” λ°©μ‹μœΌλ‘œ μΌλŒ€λ‹€(one-to-many) μ˜μ‘΄μ„±μ„ μ •μ˜ν•œλ‹€. (= μΌμ’…μ˜ λΈŒλ‘œλ“œμΊμŠ€νŒ… 방식)

  • μƒνƒœλ₯Ό 가지고 μžˆλŠ” 객체λ₯Ό Subject, 이 μƒνƒœλ₯Ό λͺ¨λ‹ˆν„°λž‘ν•˜λŠ” 객체λ₯Ό Observer라고 ν•œλ‹€.
  • 객체의 μƒνƒœ 변화에 관심 μžˆλŠ” Observerκ°€ λͺ‡ κ°œμΈμ§€μ™€ 상관 없이 μ•Œλ¦Όμ΄ 가도둝 κ΅¬ν˜„ν•΄μ•Ό ν•œλ‹€.
  • Subject, Observerλ₯Ό 뢄리 κ΅¬ν˜„ν•˜κΈ° λ•Œλ¬Έμ—, Subject와 Observerκ°€ 각각 변경사항이 생겨도 μ„œλ‘œμ—κ²Œ 영ν–₯을 λ―ΈμΉ˜μ§€ μ•ŠλŠ”λ‹€. (= λŠμŠ¨ν•œ κ²°ν•©)
    • Observerλ₯Ό μ–Έμ œλ“ μ§€ μƒˆλ‘œ μΆ”κ°€ν•˜κ±°λ‚˜ μ œκ±°ν•  수 μžˆλ‹€.
    • μƒˆλ‘œμš΄ ν˜•μ‹μ˜ Observerλ₯Ό μΆ”κ°€ν•  수 μžˆλ‹€.
  • μ΅œμ‹  μƒνƒœκ°’μ„ κ°€μ Έμ˜€λŠ” 방법은 2가지이닀.
    • 방법 1: Subjectκ°€ 전체 Observerμ—κ²Œ Pushν•˜λŠ” 방법 (= Subjectκ°€ μƒνƒœλ₯Ό 인자둜 λ„˜κ²¨ Observerμ—μ„œ λ³€κ²½)
    • 방법 2: Observerκ°€ Subjectλ‘œλΆ€ν„° μƒνƒœλ₯Ό Pullν•˜λŠ” 방법 (= update λ©”μ„œλ“œ κ΅¬ν˜„ μ‹œ getter ν•¨μˆ˜λ‘œ Subject의 μƒνƒœλ₯Ό 가져와 λ³€κ²½)

Subject

from abc import ABCMeta, abstractmethod


class Subject:
  __metaclass__ = ABCMeta

  @abstractmethod
  def registerObserver(self, observer):
    pass

  @abstractmethod
  def removeObserver(self, observer):
    pass

  @abstractmethod
  def notifyObservers():
    pass


class WeatherData(Subject):

  def __init__(self):
    self._observers = []
    self._temperature = None
    self._humidity = None
    self._pressure = None

  def registerObserver(self, observer):
    self._observers.append(observer)

  def removeObserver(self, obeserver):
    try:
      self._observers.remove(observer)
    except:
      pass

  def notifyObservers(self):
    for observer in self._observers:
      observer.update(self._temperature, self._humidity, self._pressure)

  def measurementChanged(self):
    self.notifyObservers()

  def setMeasurements(self, temperature, humidity, pressure):
    self._temperature = temperature
    self._humidity = humidity
    self._pressure = pressure

    self.measurementChanged()

Observer

class Observer:
    __metaclass__ = ABCMeta

    @abstractmethod
    def update(self, temp, humidity, pressure):
        pass


class DisplayElement:
    __metaclass__ = ABCMeta

    @abstractmethod
    def display(self):
        pass


class CurrentConditionsDisplay(Observer, DisplayElement):

    def __init__(self, weather_data):
        self._temperature = None
        self._humidity = None
        self._weather_data = weather_data

        weather_data.registerObserver(self)

    def update(self, temperature, humidity, pressure):
        self._temperature = temperature
        self._humidity = humidity
        self.display()

    def display(self):
        print(f"ν˜„μž¬ 쑰건: μ˜¨λ„ {self._temperature} Β°F / μŠ΅λ„ {self._humidity}");

3μž₯. λ°μ½”λ ˆμ΄ν„° νŒ¨ν„΄

λ””μžμΈ 원칙: OCP(Open-Closed Principle)

ν΄λž˜μŠ€λŠ” ν™•μž₯μ—λŠ” μ—΄λ € μžˆμ–΄μ•Ό ν•˜μ§€λ§Œ λ³€κ²½μ—λŠ” λ‹«ν˜€ μžˆμ–΄μ•Ό ν•œλ‹€.

https://blog.itcode.dev/posts/2021/08/14/open-closed-principle

λ°μ½”λŸ¬μ΄ν„° νŒ¨ν„΄

decorator-uml

객체에 μΆ”κ°€ μš”μ†Œλ₯Ό λ™μ μœΌλ‘œ 더할 수 μžˆλŠ” λ°©μ‹μœΌλ‘œ μ„œλΈŒν΄λž˜μŠ€λ₯Ό λ§Œλ“€ λ•Œλ³΄λ‹€ 훨씬 μœ μ—°ν•˜κ²Œ κΈ°λŠ₯을 ν™•μž₯ν•  수 μžˆλ‹€.

  • λ°μ½”λ ˆμ΄ν„° μŠˆνΌν΄λž˜μŠ€λŠ” μž₯식할 객체의 μŠˆνΌν΄λž˜μŠ€μ™€ κ°™λ‹€.
  • ν•œ 객체에 μ—¬λŸ¬ 개의 λ°μ½”λ ˆμ΄ν„°λ₯Ό κ°μŒ€ 수 μžˆλ‹€.
  • λ°μ½”λ ˆμ΄ν„°λŠ” μž₯식할 κ°μ²΄μ—κ²Œ μ–΄λ–€ 행동을 μœ„μž„ν•˜λŠ” 일 말고도 μΆ”κ°€ μž‘μ—…μ„ μˆ˜ν–‰ν•  수 μžˆλ‹€.
  • λ°μ½”λ ˆμ΄ν„°μ—μ„œ "상속"을 μ‚¬μš©ν•˜λŠ” μ΄μœ λŠ” ꡬ성 μš”μ†Œμ™€μ˜ ν˜•μ‹λ―ˆ λ§žμΆ”κΈ° μœ„ν•¨μ΄λ‹€.
    • ꡬ성 μš”μ†Œκ°€ 좔상 클래슀라면 λ˜‘κ°™μ΄ 좔상 클래슀λ₯Ό, μΈν„°νŽ˜μ΄μŠ€λΌλ©΄ μΈν„°νŽ˜μ΄μŠ€λ‘œ κ΅¬ν˜„ν•œλ‹€.
  • μƒˆλ‘œμš΄ κΈ°λŠ₯을 λ”ν•˜κ³  ꡬ성 μš”μ†ŒλŠ” λ°μ½”λ ˆμ΄ν„°μ˜ 쑴재λ₯Ό μ•Œ 수 μ—†λ‹€λŠ” μ μ—μ„œ 맀우 ν™•μž₯성이 λ†’μ§€λ§Œ, λ‹€μŒκ³Ό 같은 단점이 μžˆλ‹€.
    • μžμž˜ν•œ ν΄λž˜μŠ€κ°€ 많이 μΆ”κ°€λ˜λŠ” 경우λ₯Ό λ³Ό 수 μžˆλ‹€.
    • ꡬ성 μš”μ†Œλ₯Ό μ΄ˆκΈ°ν™”ν•˜λŠ” 데 ν•„μš”ν•œ μ½”λ“œκ°€ 훨씬 λ³΅μž‘ν•΄μ§„λ‹€.

Component

from abc import ABCMeta, abstractmethod


class Beverage:
  __metaclass__ = ABCMeta

  def __init__(self):
    self._description = "Unknown Beverage"

  def get_description(self):
    return self._description

  @abstractmethod
  def cost(self):
    pass


class Espresso(Beverage):

    def __init__(self):
      self._description = "Espresso"

    def cost(self):
      return 1.99

Decorator

class CondimentDecorator(Beverage):
  __metaclass__ = ABCMeta

  @abstractmethod
  def get_description():
    pass

class Mocha(CondimentDecorator):

  def __init__(self, beverage):
    self._beverage = beverage

  def get_description(self):
    return self._beverage.get_description() + ", Mocha"

  def cost(self):
    return .20 + self._beverage.cost()

μ‚¬μš© μ˜ˆμ‹œ

if __name__ == "__main__":
    beverage = Espresso()
    print(beverage.get_description() + " $" + str(beverage.cost()))	# Espresso $1.99

    beverage2 = Espresso()
    beverage2 = Mocha(beverage2)
    beverage2 = Mocha(beverage2)
    print(beverage2.get_description() + " $" + str(beverage2.cost()))	# Espresso, Mocha, Mocha $2.39

4μž₯. νŒ©ν† λ¦¬ νŒ¨ν„΄

μ˜μ‘΄μ„± μ—­μ „ 원칙

νŒ©ν† λ¦¬ νŒ¨ν„΄

8μž₯. ν…œν”Œλ¦Ώ λ©”μ†Œλ“œ νŒ¨ν„΄

  • 후크 λ©”μ„œλ“œ: "μ‚¬μš©ν•΄λ„ 되고 μ•ˆν•΄λ„ 되고, μ‚¬μš©ν•œλ‹€λ©΄ μˆ˜μ •ν•΄λ„ 되고"
    • ν•„μˆ˜λ‘œ μ‚¬μš©ν•΄μ•Ό ν•˜λŠ” λ©”μ„œλ“œλΌλ©΄ 좔상 λ©”μ„œλ“œλ‘œ μ •μ˜, μ„ νƒμ μœΌλ‘œ μ‚¬μš©ν•΄μ•Ό ν•˜λŠ” λ©”μ„œλ“œλΌλ©΄ 후크 λ©”μ„œλ“œλ‘œ μ •μ˜\
  • Comparable(자기 μžμ‹ κ³Ό λ§€κ°œλ³€μˆ˜ 객체 비ꡐ) vs Comparator(두 λ§€κ°œλ³€μˆ˜ 비ꡐ) (https://st-lab.tistory.com/243)
  • νƒ¬ν”Œλ¦Ώ λ©”μ„œλ“œ νŒ¨ν„΄: "μ—¬λŸ¬ λ©”μ„œλ“œλ‘œ κ΅¬μ„±λœ λ©”μ„œλ“œμ΄κ³  κ·Έ λ©”μ„œλ“œ 쀑 μΆ”μƒλ©”μ„œλ“œκ°€ μžˆμ–΄μ„œ 이걸 κ΅¬ν˜„ν•˜λŠ” νŒ¨ν„΄"(?)
  • νŒ©ν† λ¦¬ λ©”μ„œλ“œ νŒ¨ν„΄λ„ ν…œν”Œλ¦Ώ λ©”μ„œλ“œ νŒ¨ν„΄μ΄λ‹€..? (https://refactoring.guru/ko/design-patterns/factory-method)
    • μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜λŠ” λ©”μ„œλ“œκ°€ μΆ”μƒλ©”μ„œλ“œμ΄κ³ , ν…œν”Œλ¦Ώ λ©”μ„œλ“œκ°€ λ³„λ„λ‘œ 있음
  • ν…œν”Œλ¦Ώ λ©”μ„œλ“œ(상속, λ©”μ„œλ“œ, μ•Œκ³ λ¦¬μ¦˜ κ°œμš”) vs μ „λž΅(ꡬ성, 클래슀, μ•Œκ³ λ¦¬μ¦˜κ΅°)

10μž₯. μƒνƒœ νŒ¨ν„΄

  • μƒνƒœ νŒ¨ν„΄μ€ "μƒνƒœ"와 "μƒνƒœ 전이"λΌλŠ” κ°œλ…μ΄ λ“€μ–΄κ°„ μ „λž΅ νŒ¨ν„΄μ΄λ‹€.
  • μ™œ λ‹€λ₯Έ μƒνƒœ ν΄λž˜μŠ€μ—μ„œ λ‹€λ₯Έ μƒνƒœλ‘œ 전이할 λ•Œ μ»¨ν…μŠ€νŠΈ κ°μ²΄μ—μ„œ κ²Œν„° λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•΄μ„œ κ°€μ Έμ˜€λŠ”μ§€? κ·Έλƒ₯ κ°€μ Έμ˜€λ©΄ μ•ˆ λ˜λ‚˜? : getter, setter
ballMachine.setState(ballMachine.getAState())
ballMachine.setState(ballMachine.AState)

class ballMachin:
  State AState;
  ...
  
  public getAState():
    return this.AState

References