Pythonでデザインパターン 拾ノ型「Strategy」
今回はPythonの勉強しながらデザインパターンのStrategyをやってみました。
他のパターンにつきましては、以下の目次記事をご参照ください。
Strategyとは
直訳すると「戦略」ですね。
wikiには「アルゴリズムを使用者から独立したまま様々に変化させることができるようになる」とあります。
このパターンはBridgeパターンとよく似ていますが、
Bridgeパターンは機能拡張を目的としているのに対して、Strategyパターンは機能切り替えを目的にしている?と勝手に認識しています笑
いずれにしてもjavaやC#など、インタフェースがある言語ではあまり使わないパターンかな(;^ω^)
Strategyについて考えてみる
Bridgeパターンと同様の例ですが、以下のようなインタフェースがあったとします。
from abc import ABCMeta, abstractmethod class Hoge(metaclass=ABCMeta) : @abstractmethod def functionA(self) : pass
このインタフェースを実装したクラスは以下のような感じでしょうか?
class Foo(Hoge) def functionA(self) : print("Foo機能") class Bar(Hoge) def functionA(self) : print("Bar機能")
そしてこのクラスを使用するとすればこのような感じですかね?
if __name__ == "__main__" : foo = Foo() bar = Bar() foo.functionA() bar.functionA()
これでもいいのですが、Strategyパターンですと以下のようなStrategyクラスを作成します。
class Strategy(Hoge) def __init__(self, hoge: Hoge): self.setHogeHoge(hoge) def setHogeHoge(self, hoge) : self._hoge = hoge def functionA(self) : self._hoge.functionA()
そしてStrategyクラスにインスタンを設定することで機能切り替えが行えるようになります!
if __name__ == "__main__" : obj = Strategy(Foo()) obj.functionA() # Foo機能 obj.setHogeHoge(Bar()) obj.functionA() # Bar機能
サンプルコード
Bridgeパターンと同様にポケモンでピカピカ言ってるアイツを倒します。(๑◕ܫ◕๑)
BridgeパターンではSkillクラスを拡張するクラスを使ってダメージを与えていました。
今回は、"効果抜群クラス"と"効果は今ひとつクラス"を"効果クラス"で切り替えられるようにしています。
微妙な違いでわかりにくいかもですがお許しください(´ε`;)
# coding: utf-8 from abc import ABCMeta, abstractmethod # 技クラス class Skill(metaclass=ABCMeta) : def __init__(self, name : str, type : str) : self.__name = name self.__type = type def getName(self) -> str: return self.__name def getType(self) -> str: return self.__type @abstractmethod def getDamege(self) : pass # 効果クラス class EffectiveInterface(metaclass=ABCMeta) : @abstractmethod def getDamege(self, skill : Skill) : pass # Strategyパターン class Effective(EffectiveInterface) : def __init__(self, effect): self.setEffect(effect) def setEffect(self, effect) : self._effect = effect def getDamege(self, skill : Skill) : return self._effect.getDamege(skill) # 効果抜群クラス class superEffective(EffectiveInterface): def getDamege(self, skill : Skill): print("効果抜群だ!!") return skill.getDamege() * 1.5 # 効果は今ひとつクラス class notVeryEffective(EffectiveInterface): def getDamege(self, skill : Skill): print("効果は今ひとつのようだ...") return skill.getDamege() * 0.75 # 技:地震 class earthquake(Skill): def __init__(self): super().__init__("じしん", "じめん") def getDamege(self): return 100 # 技:たいあたり class taiatari(Skill): def __init__(self): super().__init__("たいあたり", "ノーマル") def getDamege(self): return 20 # 技:かぜおこし class gust(Skill): def __init__(self): super().__init__("かぜおこし", "ひこう") def getDamege(self): return 40 class Pikachu(object): def __init__(self, name, hp): self.__name = name self.__hp = hp def Damege(self, skill): if skill.getType() == 'じめん': damege = Effective(superEffective()).getDamege(skill) elif skill.getType() == 'ひこう': damege = Effective(notVeryEffective()).getDamege(skill) else: damege = skill.getDamege() self.__hp = self.__hp - damege if self.__hp <= 0 : print(self.__name, "は たおれた") print("め の まえ が まっしろ に なった") if __name__ == "__main__" : skill_taiatari = taiatari() skill_gust = gust() skill_earthquake = earthquake() pikachu = Pikachu(name = "ピカチュウ", hp = 75) # たいあたりしてみる print("------------") print(skill_taiatari.getName(), "を つかった") pikachu.Damege(skill_taiatari) # かぜおこしを使ってみる print("------------") print(skill_gust.getName(), "を つかった") pikachu.Damege(skill_gust) # じしんを使ってみる print("------------") print(skill_earthquake.getName(), "を つかった") pikachu.Damege(skill_earthquake)
結果はこんな感じです。
今回も上手に倒せましたか???
$ python Strategy.py ------------ たいあたり を つかった ------------ かぜおこし を つかった 効果は今ひとつのようだ... ------------ じしん を つかった 効果抜群だ!! ピカチュウ は たおれた め の まえ が まっしろ に なった