linuxBean14.04(171)デザインパターン:コンポジションでstrategy_headfirst.pyを書き直す

ラベル: ,
linuxBean14.04(169)Pythonでデザインパターン:Strategyのstrategy_headfirst.pyを参考にしているJavaの本の通り、コンポジションに書き換えてみます。

前の関連記事:linuxBean14.04(170)Pythonのデスクリプタの学習を少し


JavaインターフェイスをPythonの多重継承に置換する


python-patterns/strategy_headfirst.py at 5a0689ef410d297a5cde0f6857014e4b59a50000 · p--q/python-patterns

linuxBean14.04(170)Pythonのデスクリプタの学習を少しの内容を受けて、JavaのインターフェイスをPythonの多重継承にしました。


だけど「Head Firstデザインパターン ―頭とからだで覚えるデザインパターンの基本」のp5には継承はいまいち、と書いてあります、Javaでの話ですが。

抽象クラス(Duck)にメソッドを追加すると、すべての具象クラスでメソッドをオーバーライドする手間が増えるので保守の観点からは適切ではないと書いてあります。

「自分で考えてみよう」の答えは、A.コードがサブクラス間で重複する、D.すべての鴨の振舞いを把握するのが困難である、F.変更によって無意識に他の鴨に影響を与える可能性がある、ということですかね。

Sharpen Your Pencil - Head First Design Patterns page 5に答えがありました。

B.実行時の振舞いを変更するのが困難である、も答えでした。

p9に解説に該当する説明があります。

Pythonの上記のコードで該当するデメリットは、なさそうですけど。

多重継承の代わりにコンポジションを利用する


コンポジションにするために、多重継承しているクラスを、クラスの中でインスタンス化してそのメソッドを使うように変更しました。

python-patterns/strategy_headfirst.py at d2c1de5b6ceeef9b48550e87cf74fb8b44ddce8a · p--q/python-patterns


ちゃんとコンポジションになっていますが、かなり複雑なUML図になっています。

python-patterns/strategy_headfirst.py at 459c9313295f343cd8540fd1a7e145e4554d1f64 · p--q/python-patterns


QuackBehaviorクラスのメソッドはどれもインスタンス変数を使っていないので、インスタンス化せずに静的メソッドにしました。

そうするとクラス名の属性でメソッドを呼び出して実行できるようになります。

staticmethod()は使わなくても実行できますが、使わないとPyDevでエラーと言われるのでデコレーターの@staticmethodを付けました。

UML図ではQuackBehaviorクラスはインスタンス化していないので、枝が表示されていません。

コンポジションに代わって集約を利用する


composition and aggregation in python - Stack Overflow

Pythonの「コンポジション」と「集約」の例がありました。

クラスの中でインスタンス化しなければ「集約」と判断されるようです。

python-patterns/strategy_headfirst.py at 924a5f9a693d71c93fa7c6373d2023874bccefa7 · p--q/python-patterns


FlyBehaviorクラスをDuckサブクラスの外でインスタンス化して引数で渡すようにしました。

「集約」の枝を表示させたかったのですが、どういうコードにすれば「集約」の枝を表示してくれるのかわかりませんでした。

pylint/writer.py at master · PyCQA/pylint

pyreverseのソースを見ても、arrowhead='diamond', style='solid'というのしか見つけられなかったので、「集約」の枝は用意されていないのかもしれません。

結局多重継承できるPythonでは、素直に多重継承を使うのが一番すっきりしたコードになるように思いました。

参考にしたサイト


composition and aggregation in python - Stack Overflow
Pythonでの「コンポジション」と「集約」の例。

pylint/writer.py at master · PyCQA/pylint
pyreverseのソース。「集約」の枝は用意されていないように思えます。

次の関連記事:linuxBean14.04(172)Observerパターン:Subjectを実装しない方法

PR

0 件のコメント:

コメントを投稿