Pythonで振る舞いに関するデザインパターンを作成してみた

## 目次
[● Chain of Responsibility パターン](#-chain-of-responsibility-パターン)
[● Command パターン](#-command-パターン)
[● Interpreter パターン](#-interpreter-パターン)
[● Iterator パターン](#-iterator-パターン)
[● Mediator パターン](#-mediator-パターン)
[● Memento パターン](#-memento-パターン)
[● Observer パターン](#-observer-パターン)
[● State パターン](#-state-パターン)
[● Strategy パターン](#-strategy-パターン)
[● Template Method パターン](#-template-method-パターン)
[● Visitor パターン](#-visitor-パターン)
[その他のデザインパターン](#その他のデザインパターン)

## <font color="DarkGray">●</font><font color="DeepSkyBlue"> Chain of Responsibility パターン</font>
```python:ChainOfResponsibility.py
# ----------------------------------------------------------------------
#                　Chain of Responsibility パターン
# ----------------------------------------------------------------------
# 処理の責任をたらい回しにします。

from abc import ABCMeta, abstractmethod


class Handler(metaclass=ABCMeta):
    def __init__(self, next_handler=None):
        self.next_handler = next_handler

    @abstractmethod
    def handle(self, day):
        pass


class Handler01(Handler):
    def handle(self, day):
        if day <= 2:
            print('{}日の休暇を承認した。承認者：Handler01'.format(str(day)))
        else:
            self.next_handler.handle(day)


class Handler02(Handler):
    def handle(self, day):
        if 2 < day <= 5:
            print('{}日の休暇を承認した。承認者：Handler02'.format(str(day)))
        else:
            self.next_handler.handle(day)


class FinalHandler99(Handler):

    def handle(self, day):
        if 5 < day <= 10:
            print('{}日の休暇を承認した。承認者：FinalHandler99'.format(str(day)))
        else:
            print('11日以上の休暇を承認できない。承認者：FinalHandler99'.format(str(day)))


class Client:
    def __init__(self):
        h99 = FinalHandler99()
        h02 = Handler02(h99)
        self.handler = Handler01(h02)

    def get_handler(self):
        return self.handler


if __name__ == '__main__':
    h = Client().get_handler()
    for day in [2, 9, 3]:
        h.handle(day)
```
実行結果：
```
2日の休暇を承認した。承認者：Handler01
9日の休暇を承認した。承認者：FinalHandler99
3日の休暇を承認した。承認者：Handler02
```
## <font color="DarkGray">●</font><font color="DeepSkyBlue"> Command パターン</font>

```python:Command.py
# ----------------------------------------------------------------------
#                　Command パターン
# ----------------------------------------------------------------------
# コマンドをクラスで表現します。

from abc import ABCMeta, abstractmethod


# 抽象コマンドクラス
class Command(metaclass=ABCMeta):
    def __init__(self, receiver):
        self.receiver = receiver

    @abstractmethod
    def execute(self):
        pass


# 具象コマンドクラス　
class StartCommand(Command):
    def execute(self):
        self.receiver.start()


# 具象コマンドクラス
class StopCommand(Command):
    def execute(self):
        self.receiver.stop()


# 具体的なアクションを定義するクラス
class Receiver:
    def start(self):
        print('処理内容: スタートアクション')

    def stop(self):
        print('処理内容: ストップアクション')


# コマンドを受け入れ、コマンドを実行するクラス
class Invoker:
    def __init__(self):
        self.commands = []

    def add_command(self, command):
        self.commands.append(command)

    def remove_command(self, command):
        self.commands.remove(command)

    def run_command(self):
        for cmd in self.commands:
            cmd.execute()


if __name__ == '__main__':
    receiver = Receiver()
    start_cmd = StartCommand(receiver)
    stop_cmd = StopCommand(receiver)
    inv = Invoker()
    inv.add_command(start_cmd)
    inv.add_command(stop_cmd)
    inv.run_command()
```
実行結果：
```
処理内容: スタートアクション
処理内容: ストップアクション
```
## <font color="DarkGray">●</font><font color="DeepSkyBlue"> Interpreter パターン</font>

```python:Interpreter.py
# ----------------------------------------------------------------------
#                　Interpreter パターン
# ----------------------------------------------------------------------
# 構文を解析し、規則をクラスで表現します。

from abc import ABCMeta, abstractmethod


class Expression(metaclass=ABCMeta):
    @abstractmethod
    def interpret(self, context=None):  # contextは未使用
        pass


class ValueExpression(Expression):
    def __init__(self, value):
        self.value = value

    def interpret(self, context=None):
        return self.value


class OperatorExpression(Expression):
    def __init__(self, left, right):
        self.left = left
        self.right = right

    def interpret(self, context=None):
        pass


# 加算
class PlusExpression(OperatorExpression):
    def __init__(self, left, right):
        self.node = OperatorExpression(left, right)

    def interpret(self, context=None):
        return self.node.left.interpret() + self.node.right.interpret()


# 引き算
class SubExpression(OperatorExpression):
    def __init__(self, left, right):
        self.node = OperatorExpression(left, right)

    def interpret(self, context=None):
        return self.node.left.interpret() - self.node.right.interpret()


# 乗算
class MulExpression(OperatorExpression):
    def __init__(self, left, right):
        self.node = OperatorExpression(left, right)

    def interpret(self, context=None):
        return self.node.left.interpret() * self.node.right.interpret()


# 除算
class DivExpression(OperatorExpression):
    def __init__(self, left, right):
        self.node = OperatorExpression(left, right)

    def interpret(self, context=None):
        return self.node.left.interpret() / self.node.right.interpret()


# 中置記法（数式）を後置記法に変換するクラス
class Postfix:
    def is_numeric(self, s):
        try:
            float(s)
        except ValueError:
            return False
        else:
            return True

    # 後置記法の配列を取得
    def get_postfix(self, expr):
        operator_dict = {"*": 30, "/": 30, "+": 20, "-": 20, "(": 10, ")": 10}

        stack = []
        postfix_list = []
        infix_expr = expr.replace(' ', '')
        token_list = []
        temstr = ''
        for i in range(len(infix_expr)):
            char = infix_expr[i]
            is_operator = char in operator_dict.keys()
            if char == '-':
                if i == 0:
                    is_operator = False
                else:
                    if infix_expr[i - 1] == '(':
                        is_operator = False

            if is_operator:
                if len(temstr) != 0:
                    token_list.append(temstr)
                    temstr = ''
                token_list.append(char)
            else:
                temstr = temstr + char
        if len(temstr) != 0:
            token_list.append(temstr)

        for token in token_list:
            if self.is_numeric(token):
                postfix_list.append(token)
            elif token == "(":
                stack.append(token)
            elif token == ")":
                top_token = stack.pop()
                while top_token != "(":
                    postfix_list.append(top_token)
                    top_token = stack.pop()
            else:
                while len(stack) != 0 and operator_dict[stack[-1]] >= operator_dict[token]:
                    postfix_list.append(stack.pop())
                stack.append(token)
        while len(stack) != 0:
            postfix_list.append(stack.pop())

        return postfix_list


class Calculator:
    def __init__(self):
        self.root_expression = None
        self.cal_success = True
        self.postfix_list = []

    # 二分木を構築
    def get_binary_tree(self, exp):
        p = Postfix()
        self.postfix_list = p.get_postfix(exp)   # 後置記法の配列
        f = lambda x: float(x) if p.is_numeric(x) else x
        post_list = list(map(f, self.postfix_list))
        # 二分木を構築
        expression_stack = []
        operators = '+-*/'
        for postfix in post_list:
            item = str(postfix)
            if item in operators:
                right = expression_stack[-1]
                left = expression_stack[-2]
                expression_stack = expression_stack[0:-2]
                if item == '+':
                    expression_stack.append(PlusExpression(left, right))
                elif item == '-':
                    expression_stack.append(SubExpression(left, right))
                elif item == '*':
                    expression_stack.append(MulExpression(left, right))
                elif item == '/':
                    expression_stack.append(DivExpression(left, right))
            else:
                expression_stack.append(ValueExpression(postfix))

        return expression_stack[0]

    def get_expression_value(self, expression):
        self.cal_success = True
        rtn = 0
        try:
            self.root_expression = self.get_binary_tree(expression)
            rtn = self.root_expression.interpret()
        except Exception as e:
            self.cal_success = False
            print('不正な数式:[{}]  (error:{})'.format(expression, e))

        return rtn


if __name__ == '__main__':
    # ----- Client -----
    exp_list = []
    exp_list.append('((3+5)/(10-8))*(2+3)')
    exp_list.append('5*(-12.5 - 3)')
    exp_list.append('-2*2 - (-9)')
    cal = Calculator()
    for exp in exp_list:
        val = cal.get_expression_value(exp)
        if cal.cal_success:
            print('後置記法の数式：[{}]'.format('  '.join(cal.postfix_list)))
            print('{} = {}'.format(exp, val))
```
実行結果：
```
後置記法の数式：[3  5  +  10  8  -  /  2  3  +  *]
((3+5)/(10-8))*(2+3) = 20.0
後置記法の数式：[5  -12.5  3  -  *]
5*(-12.5 - 3) = -77.5
後置記法の数式：[-2  2  *  -9  -]
-2*2 - (-9) = 5.0
```
## <font color="DarkGray">●</font><font color="DeepSkyBlue"> Iterator パターン</font>

```python:Iterator.py
# ----------------------------------------------------------------------
#                　          Iterator パターン
# ----------------------------------------------------------------------
# 集合の各要素に順次にアクセスする方法を提供します。

from abc import ABCMeta, abstractmethod


class Iterator(metaclass=ABCMeta):
    @abstractmethod
    def has_next(self):
        pass

    @abstractmethod
    def next(self):
        pass


class Student:
    def __init__(self, name):
        self.name = name

    def show_info(self):
        print(self.name)


class StudentIterator(Iterator):
    def __init__(self, students):
        # 学生名を基準に降順でソート
        self.students = sorted(students, key=lambda x: x.name, reverse=True)
        self.index = 0

    def has_next(self):
        if self.students is None:
            return False
        return self.index < len(self.students)

    def next(self):
        stu = self.students[self.index]
        self.index += 1
        return stu


if __name__ == '__main__':
    students = [Student('学生A'), Student('学生C'), Student('学生B')]
    student_iterator = StudentIterator(students)

    while student_iterator.has_next():
        student = student_iterator.next()
        student.show_info()
```
実行結果：
```
学生C
学生B
学生A
```
## <font color="DarkGray">●</font><font color="DeepSkyBlue"> Mediator パターン</font>

```python:Mediator.py
# ----------------------------------------------------------------------
#                　          Mediator パターン
# ----------------------------------------------------------------------
# オブジェクト間の関係を中間オブジェクトで制御します。

from abc import ABCMeta, abstractmethod


class Mediator(metaclass=ABCMeta):
    @abstractmethod
    def send(self, message, colleague):
        pass


class Colleague(metaclass=ABCMeta):
    def __init__(self, mediator):
        self.mediator = mediator

    @abstractmethod
    def send(self, message):
        pass

    @abstractmethod
    def notify(self, message):
        pass


class ConcreteColleagueA(Colleague):

    def send(self, message):
        self.mediator.send(message, self)

    def notify(self, message):
        print('同僚Aが入手した情報：{}'.format(message))


class ConcreteColleagueB(Colleague):
    def send(self, message):
        self.mediator.send(message, self)

    def notify(self, message):
        print('同僚Bが入手した情報：{}'.format(message))


class ConcreteMediator(Mediator):
    def __init__(self):
        self.__colleagueA = None
        self.__colleagueB = None

    @property
    def colleagueA(self):
        return

    @colleagueA.setter
    def colleagueA(self, value):
        self.__colleagueA = value

    @property
    def colleagueB(self):
        return

    @colleagueB.setter
    def colleagueB(self, value):
        self.__colleagueB = value

    def send(self, message, colleague):
        if colleague == self.__colleagueA:
            self.__colleagueB.notify(message)
        else:
            self.__colleagueA.notify(message)


if __name__ == "__main__":
    m = ConcreteMediator()
    a = ConcreteColleagueA(m)
    b = ConcreteColleagueB(m)

    m.colleagueA = a
    m.colleagueB = b

    a.send('運動が好きです。')
    b.send('音楽が好きです。')
```
実行結果：
```
同僚Bが入手した情報：運動が好きです。
同僚Aが入手した情報：音楽が好きです。
```
## <font color="DarkGray">●</font><font color="DeepSkyBlue"> Memento パターン</font>

```python:Memento.py
# ----------------------------------------------------------------------
#                　Memento パターン
# ----------------------------------------------------------------------
# ある時点のオブジェクトの状態を保存し、オブジェクトを復元できるようにします。

class Originator:
    def __init__(self, state, val):
        self.state = state
        self.val = val

    def save_memento(self):
        return Memento(self.state, self.val)

    def recover_memento(self, memento):
        self.state = memento.state
        self.val = memento.val

    def show_infor(self):
        print('state: {}  val: {}'.format(self.state, self.val))


class Memento:
    def __init__(self, state, val):
        self.state = state
        self.val = val


class Caretaker:
    def __init__(self, memento):
        self.memento = memento


if __name__ == '__main__':
    originator = Originator('状態1', 10)
    originator.show_infor()
    memento_temp = originator.save_memento()
    caretaker = Caretaker(memento_temp)
    originator.state = '状態2'
    originator.val = 60
    originator.show_infor()
    originator.recover_memento(caretaker.memento)
    originator.show_infor()

```
実行結果：
```
state: 状態1  val: 10
state: 状態2  val: 60
state: 状態1  val: 10
```
## <font color="DarkGray">●</font><font color="DeepSkyBlue"> Observer パターン</font>

```python:Observer.py
# ----------------------------------------------------------------------
#                　    Observer パターン
# ----------------------------------------------------------------------
# 状態の変化を複数のオブジェクトに通知します。

from abc import ABCMeta, abstractmethod


# 抽象観察者
class Observer(metaclass=ABCMeta):
    @abstractmethod
    def update(self, notice):
        pass


# 発信者(基底)
class Notice:
    def __init__(self):
        self.observers = []

    def attach(self, obs):
        if obs not in self.observers:
            self.observers.append(obs)

    def detach(self, obs):
        try:
            self.observers.remove(obs)
        except ValueError:
            pass

    def notify(self):
        for obs in self.observers:
            obs.update(self)


# 観察者
class StudentObserver(Observer):
    def __init__(self, name):
        self.name = name
        self.status = ''
        self.notice = None

    def register(self, notice):
        self.notice = notice
        notice.attach(self)

    def unregister(self):
        if self.notice:
            self.notice.detach(self)
            self.notice = None

    def update(self, notice):
        self.status = notice.status

    def show_status(self):
        print('{}：{}'.format(self.name, self.status))


# 発信者
class NoticeCenter(Notice):
    def __init__(self):
        super().__init__()
        self.__status = ''

    @property
    def status(self):
        return self.__status

    @status.setter
    def status(self, status):
        self.__status = status
        self.notify()


if __name__ == '__main__':
    notice_center = NoticeCenter()
    stu1 = StudentObserver('学生A')
    stu1.register(notice_center)
    stu2 = StudentObserver('学生B')
    stu2.register(notice_center)

    notice_center.status = '休憩開始'
    stu1.show_status()
    stu2.show_status()

    notice_center.status = '休憩終了'
    stu1.show_status()
    stu2.show_status()
```
実行結果：
```
学生A：休憩開始
学生B：休憩開始
学生A：休憩終了
学生B：休憩終了
```
## <font color="DarkGray">●</font><font color="DeepSkyBlue"> State パターン</font>

```python:State.py
# ----------------------------------------------------------------------
#                　          State パターン
# ----------------------------------------------------------------------
# 状態をクラスとして表現します。（クラスを切り替えることで「状態の変化」を表します）
from abc import ABCMeta, abstractmethod


# 抽象状態
class State(metaclass=ABCMeta):
    @abstractmethod
    def heat(self):
        pass

    @abstractmethod
    def cool(self):
        pass


# 液体状態を表すクラス
class Water(State):
    def heat(self):
        return Vapour()

    def cool(self):
        return Ice()

    def __str__(self):
        return '液体状態の水'


# 気体状態を表すクラス
class Vapour(State):
    def heat(self):
        return self

    def cool(self):
        return Water()

    def __str__(self):
        return '気体状態の水'


# 個体状態を表すクラス
class Ice(State):
    def heat(self):
        return Water()

    def cool(self):
        return self

    def __str__(self):
        return '個体状態の水'


class Context:
    def __init__(self, state):
        self.state = state

    def heat(self):
        self.state = self.state.heat()

    def cool(self):
        self.state = self.state.cool()

    def set_state(self, state):
        self.state = state


if __name__ == '__main__':
    context = Context(Ice())  # 初期：個体状態
    for i in range(0, 2):
        pre_state = format(context.state)
        context.heat()
        print('{} →　加熱後 →　{}'.format(pre_state, context.state))
    print('-' * 35)
    for i in range(0, 3):
        pre_state = format(context.state)
        context.cool()
        print('{} →　冷却後 →　{}'.format(pre_state, context.state))
```
実行結果：
```
個体状態の水 →　加熱後 →　液体状態の水
液体状態の水 →　加熱後 →　気体状態の水
-----------------------------------
気体状態の水 →　冷却後 →　液体状態の水
液体状態の水 →　冷却後 →　個体状態の水
個体状態の水 →　冷却後 →　個体状態の水
```
## <font color="DarkGray">●</font><font color="DeepSkyBlue"> Strategy パターン</font>

```python:Strategy.py
# ----------------------------------------------------------------------
#                　          Strategy パターン
# ----------------------------------------------------------------------
# 各種のアルゴリズムを定義し、相互に置き換えられるようにします。
from abc import ABCMeta, abstractmethod


class Strategy(metaclass=ABCMeta):
    @abstractmethod
    def run(self):
        pass


class StrategyAlgorithm1(Strategy):
    def run(self):
        print('アルゴリズム1での処理')


class StrategyAlgorithm2(Strategy):
    def run(self):
        print('アルゴリズム2での処理')


class Context:
    def __init__(self, strategy):
        self.strategy = strategy

    def set_strategy(self, strategy):
        self.strategy = strategy

    def do_strategy(self):
        self.strategy.run()


if __name__ == '__main__':
    c = Context(StrategyAlgorithm1())
    c.do_strategy()
    c.set_strategy(StrategyAlgorithm2())
    c.do_strategy()

```
実行結果：
```
アルゴリズム1での処理
アルゴリズム2での処理
```
## <font color="DarkGray">●</font><font color="DeepSkyBlue"> Template Method パターン</font>

```python:TemplateMethod.py
# ----------------------------------------------------------------------
#                　Template Method パターン
# ----------------------------------------------------------------------
# 抽象クラスで処理の枠組みを定め、サブクラスでその具体的な内容を実装します。
from abc import ABCMeta, abstractmethod


class Template(metaclass=ABCMeta):

    @abstractmethod
    def method1(self):
        pass

    @abstractmethod
    def method2(self):
        pass

    def start_common(self):
        print('Template:start_common')

    def stop_common(self):
        print('Template:stop_common')

    def run(self):
        self.start_common()
        self.method1()
        self.method2()
        self.stop_common()


class SubClassA(Template):
    def method1(self):
        print('SubClassA:method1')

    def method2(self):
        print('SubClassA:method2')


class SubClassB(Template):
    def method1(self):
        print('SubClassB:method1')

    def method2(self):
        print('SubClassB:method2')


if __name__ == '__main__':
    s_a = SubClassA()
    s_b = SubClassB()
    s_a.run()
    print('--------------------')
    s_b.run()
```
実行結果：
```
Template:start_common
SubClassA:method1
SubClassA:method2
Template:stop_common
--------------------
Template:start_common
SubClassB:method1
SubClassB:method2
Template:stop_common
```
## <font color="DarkGray">●</font><font color="DeepSkyBlue"> Visitor パターン</font>

```python:Visitor.py
# ----------------------------------------------------------------------
#                　          Visitor パターン
# ----------------------------------------------------------------------
# 機能をビジターに記述することで、処理の追加を簡単にします。

from abc import ABCMeta, abstractmethod


class AnimalElement(metaclass=ABCMeta):
    @abstractmethod
    def accept(self, visitor):
        pass


class Visitor(metaclass=ABCMeta):
    @abstractmethod
    def visit_cat(self, cat_element):
        pass

    def visit_dog(self, dog_element):
        pass


class CatElement(AnimalElement):
    def accept(self, visitor):
        visitor.visit_cat(self)


class DogElement(AnimalElement):
    def accept(self, visitor):
        visitor.visit_dog(self)


class OwnerVisitor(Visitor):
    def visit_cat(self, cat_element):
        print('visit_cat in OwnerVisitor')
        print('Ownerビジターの処理：猫に餌をやるアクション')

    def visit_dog(self, dog_element):
        print('visit_dog in OwnerVisitor')
        print('OwnerVisitorの処理：犬に餌をやるアクション')


class ChildVisitor(Visitor):
    def visit_cat(self, cat_element):
        print('visit_cat in ChildVisitor')
        print('ChildVisitorの処理：猫に餌をやるアクション')

    def visit_dog(self, dog_element):
        print('visit_dog in ChildVisitor')
        print('ChildVisitorの処理：犬に餌をやるアクション')


class Home(list):
    def act(self, visitor):
        for e in self:
            e.accept(visitor)


if __name__ == '__main__':
    home = Home()
    home.append(CatElement())
    home.append(DogElement())
    home.act(OwnerVisitor())
    print('-' * 50)
    home.act(ChildVisitor())
```
実行結果：
```
visit_cat in OwnerVisitor
Ownerビジターの処理：猫に餌をやるアクション
visit_dog in OwnerVisitor
OwnerVisitorの処理：犬に餌をやるアクション
--------------------------------------------------
visit_cat in ChildVisitor
ChildVisitorの処理：猫に餌をやるアクション
visit_dog in ChildVisitor
ChildVisitorの処理：犬に餌をやるアクション
```
## その他のデザインパターン
[Pythonで生成に関するデザインパターンを作成してみた](https://qiita.com/lxk/items/f62611a34005f1c087b0)
[Pythonで構造に関するデザインパターンを作成してみた](https://qiita.com/lxk/items/939300b9ff328a79c5b6)

***