週末!プログラミング部

ソフトウェア開発ネタを中心に自分でいろいろ調べた内容を自分の勝手な解釈で思うがままに書いくためのブログ。サンプルソースコード、API、プラットフォーム、プログラミング言語、開発環境などを調査、分析して追求いく予定です。

Pythonでデザインパターン 拾弐ノ型「Decorator」

今回はPythonの勉強しながらデザインパターンのDecoratorをやってみました。
他のパターンにつきましては、以下の目次記事をご参照ください。

Decoratorとは

直訳すると「飾り付けをする人」ですかね。
wikiには「既存のオブジェクトに新しい機能や振る舞いを動的に追加することを可能にする」とあります。

直訳やwikiから推測するにいまあるオブジェクトに飾り付けを行うためのパターンのようです。
゚+.(◕ฺ ω◕ฺ )゚+.

Decoratorについて考えてみる

今回は顔文字をデコってみたいと思います(・`ω´・)b

まずはデコレーションするベースクラスComponentを用意します。

class Component(metaclass=ABCMeta):
    @abstractmethod
    def getTxt(self):
        pass

そしてComponentを使って顔文字クラスEmoticonを作ります。

class Emoticon(Component):
    def getTxt(self):
        return "(^ω^)"

Emoticonクラスだけ使うとこんな感じです。
派手さが足りませんね(・´ω`・)

> print(Emoticon().getTxt())
(^ω^)

次にComponentクラスをデコレートするためのベースクラスDecoratorを用意します。
DecoratorクラスにはComponentクラスを継承させます。

class Decorator(Component):
    def __init__(self, component: Component) :
        self._component = component

そしてDecoratorクラスをもとにデコレートするクラスを準備します。

class BanzaiDecorator(Decorator):
    def __init__(self, component: Component) :
        super().__init__(component)

    def getTxt(self):
        return "ヽ" + self._component.getTxt() + "/"

あとは使うだけですね!
EmoticonクラスをBanzaiDecoratorクラスでラッピングしてデコレートしていますヽ(^ω^)/

> print(BanzaiDecorator(Emoticon()).getTxt())
ヽ(^ω^)/

こんな感じでオブジェクトをラップして機能をデコレートしていくパターンになります。

サンプルコード

顔文字に万歳、Yeah、きらきらをデコレーションしてみます。

# coding: utf-8

from abc import ABCMeta, abstractmethod

# コンポーネントクラス
class Component(metaclass=ABCMeta):
    @abstractmethod
    def getTxt(self):
        pass

# デコレータクラス
class Decorator(Component):
    def __init__(self, component: Component) :
        self._component = component

# 顔文字クラス
class Emoticon(Component):
    def __init__(self, text: str):
        self._text = text
    
    def getTxt(self):
        return self._text

# 万歳デコレータクラス
class BanzaiDecorator(Decorator):
    def __init__(self, component: Component) :
        super().__init__(component)

    def getTxt(self):
        return "ヽ" + self._component.getTxt() + "/"

# イエーイデコレータクラス
class YeahDecorator(Decorator):
    def __init__(self, component: Component) :
        super().__init__(component)

    def getTxt(self):
        return "イエェェェェ" + self._component.getTxt() + "ェェェェイィ"

# きらきらデコレータクラス
class GlitterDecorator(Decorator):
    def __init__(self, component: Component) :
        super().__init__(component)

    def getTxt(self):
        return "。*:゜☆" + self._component.getTxt() + "☆゜:。*。"

if __name__ == "__main__":
    
    print(Emoticon("(*´Д`)").getTxt())
    print("")
    
    print(BanzaiDecorator(
        Emoticon("(*´Д`)")).getTxt())
    print("")
    
    print(YeahDecorator(
        BanzaiDecorator(
            Emoticon("(*´Д`)"))).getTxt())
    print("")
    
    print(GlitterDecorator(
        YeahDecorator(
            BanzaiDecorator(
                Emoticon("(*´Д`)")))).getTxt())

結果はこんな感じ。
きれいにデコレーションできましたか???

$ python Decorator.py
(*´Д`)

ヽ(*´Д`)/

イエェェェェヽ(*´Д`)/ェェェェイィ

。*:゜☆イエェェェェヽ(*´Д`)/ェェェェイィ☆゜:。*。