μΉ΄ν…Œκ³ λ¦¬ μ—†μŒ

[OOP] Decorator Pattern

loki d 2021. 9. 4. 22:44
728x90

μž₯식 νŒ¨ν„΄

  • νŒ¨ν„΄μ˜ λͺ©μ  : This pattern attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality. – GoF –

  • νŒ¨ν„΄μ˜ μ‚¬μš©

    • 상속에 μ˜ν•œ μ œμ•½μ‚¬ν•­μ— ꡬ속 λ°›μ§€ μ•Šκ³  λ™μ μœΌλ‘œ 객체에 μƒˆλ‘œμš΄ μ±…μž„(ν–‰μœ„, μƒνƒœ)을 μΆ”κ°€ν•˜κ³  싢을 경우 (λ‹€λ₯Έ 동일 νƒ€μž… κ°μ²΄λ“€μ—κ²Œ 영ν–₯을 μ£Όμ§€ μ•Šκ³ )
    • μ‹œμŠ€ν…œμ΄ λ™μž‘ν•˜λ©΄μ„œ 객체에 κΈ°λŠ₯을 μΆ”κ°€ν•˜κ³  μ œκ±°ν•˜κ³  싢을 경우
    • λ™μ μœΌλ‘œ 객체에 μΆ”κ°€ν•  수 μžˆλŠ” μ„œλ‘œ 독립적인 λ‹€μ–‘ν•œ κΈ°λŠ₯이 μ‘΄μž¬ν•  λ•Œ
    • 상속을 톡해 객체의 μ±…μž„μ„ ν™•μž₯ν•˜κΈ° μ–΄λ €μšΈ 경우
  • νŒ¨ν„΄ 적용 κ°€λŠ₯ μ‹œλ‚˜λ¦¬μ˜€

    • 예1) GUIμ—μ„œ μœˆλ„μš° μž₯식 (μŠ€ν¬λ‘€λ°”κ°€ μžˆλŠ” μœˆλ„μš°)
    • 예2) 파일 μ²˜λ¦¬μ—μ„œ κΈ°λ³Έ 처리λ₯Ό μž₯μ‹ν•˜μ—¬ 버퍼링 지원, μ••μΆ•, μ•”ν˜Έν™” 등을 μ§€μ›ν•˜λ„λ‘ λ§Œλ“€ 수. 있음
  • νŒ¨ν„΄μ˜ μ°Έμ—¬μž

    • μž₯식 λŒ€μƒ 좔상 클래슀 λ˜λŠ” interface: λͺ¨λ“  μž₯식 λŒ€μƒμžμ΄ κ°–μΆ”μ–΄μ•Ό ν•˜λŠ” μ±…μž„ μ •μ˜
    • μž₯식 λŒ€μƒ 클래슀 : μž₯식 λŒ€μƒμ€ μž₯μ‹μžλ“€μ˜ 쑴재λ₯Ό 인식할 ν•„μš”κ°€ μ—†μŒ
    • μž₯μ‹μž 좔상 클래슀 : κΌ­ ν•„μš”ν•˜μ§€ μ•Šμ„ 수 있음. ꡬ체적 μž₯식μž₯ ν΄λž˜μŠ€κ°€ λ°˜λ“œμ‹œ μž¬μ •μ˜ν•΄μ•Ό ν•˜λŠ” λ©”μ†Œ λ“œλ₯Ό μ •μ˜ν•˜λŠ”λ° μœ μš©ν•˜κ³ , μž₯μ”© μžμ™€ μž₯식 λŒ€μƒμ„ ꡬ뢄할 수 μžˆλŠ” νƒ€μž…μœΌλ‘œ ν™œμš© κ°€λŠ₯함
    • ꡬ체적 μž₯식μž₯ 클래슀: μž₯식 λŒ€μƒμ— μΆ”κ°€ν•  μ±…μž„μ΄ μ •μ˜λ˜μ–΄ 있음. μž₯식 λŒ€μƒμ„ 멀버 λ³€μˆ˜(has-a)둜 유 μ§€ν•˜λ©°, 이 λŒ€μƒμ€ 이미 λ‹€λ₯Έ μž₯식μž₯에 μ˜ν•΄ μž₯μ‹λ˜μ–΄ μžˆμ„ 수 있음. μž₯식 λŒ€μƒμ„ ꡬ체적 μž₯식μž₯ 클래슀 λŒ€μ‹ μ— μž₯식μž₯ 좔상 ν΄λž˜μŠ€μ—μ„œ μœ μ§€ν•  수 있음. μž₯μ‹λœ κ°μ²΄λŠ” μž₯식 λŒ€μƒμ΄ μ‚¬μš©λ  수 μžˆλŠ” λͺ¨λ“  κ³³μ—μ„œ μ‚¬μš©λ  수 μžˆμ–΄μ•Ό 함
  • νŒ¨ν„΄μ˜ ꡬ쑰

    μŠ€ν¬λ¦°μƒ· 2021-07-26 μ˜€μ „ 12 32 02

  • μ°Έμ—¬μžκ°„ ν˜‘λ ₯

    • μž₯μ‹μž κ°μ²΄λŠ” μž₯식 λŒ€μƒμ„ 포함 관계λ₯Ό μœ μ§€ν•˜λ©°, μž₯μ‹μž κ°μ²΄λŠ” μž₯μ‹ν•œ κ°€μž₯ λ°”κΉ₯ κ°μ²΄ν•˜κ³ λ§Œ μ†Œν†΅ν•¨. 보톡 μ–΄λ–€ ν–‰μœ„μ— λŒ€ν•œ μš”κ΅¬λ₯Ό λ°›μœΌλ©΄ ν•΄λ‹Ή μš”κ΅¬λ₯Ό κ°€μž₯ λ°”κΉ₯ κ°μ²΄μ—κ²Œ μ „λ‹¬ν•˜λ©°, 이 과정이 κ°€μž₯ μ•ˆμͺ½ 객체(μž₯식 λŒ€μƒ)κΉŒμ§€ μ „λ‹¬λ˜μ–΄ μ΅œμ’… μ±…μž„μ˜ μˆ˜ν–‰μ΄ μ™„μ„±λ˜λŠ” ν˜•νƒœμž„. μ΄λ•Œ μš”κ΅¬λ₯Ό μ „λ‹¬ν•˜κΈ° 전에 μž₯식 자만의 λ…νŠΉν•œ κΈ°λŠ₯을 μˆ˜ν–‰ν•˜κ±°λ‚˜ μš”κ΅¬λ₯Ό μ „λ‹¬ν•˜κ³  κ·Έ κ²°κ³Όλ₯Ό λ°›μœΌλ©΄ 좔가적인 κΈ°λŠ₯을 μˆ˜ν–‰ν•˜μ—¬ μ΅œμ’… κ²°κ³Όλ₯Ό μ™„μ„±ν•˜λŠ” ν˜•νƒœμž„
class Beverage():
    def __init__(self, description="이름 μ—†λŠ” 음료"):
        self.description = description

    def getDescription(self):
        return self.description

    @abstractmethod
    def cost(self):
        pass

class CondimentDecorator(Beverage):
    @abstractmethod
    def getDescription(self):
        pass

class DarkRoast(Beverage):
    def __init__(self):
        Beverage.__init__(self, "DarkRoast")
    def cost(self):
        return 2100


class Mocha(CondimentDecorator):
    def __init__(self, beverage):
        if not isinstance(beverage, Beverage):
            raise TypeError("must use Beverage")
        self.beverage = beverage
    def getDescription(self):
        return self.beverage.getDescription()+ ", Mocha"
    def cost(self):
        return self.beverage.cost()+200


beverage = DarkRoast()
beverage = Mocha(beverage)
beverage = Mocha(beverage)
print(beverage.getDescription())
print(beverage.cost())