Pythonでデザインパターン 玖ノ型「Bridge」
今回はPythonの勉強しながらデザインパターンのBridgeをやってみました。
他のパターンにつきましては、以下の目次記事をご参照ください。
Bridgeとは
直訳すると「橋」ですね。
wikiには「"橋渡し"のクラスを用意することによって、クラスを複数の方向に拡張させることを目的とする」とあります。
このパターンは、オブジェクトとオブジェクトの間にワンクッション挟むイメージです。
JavaやC#みたいにインタフェース機能がある言語だとあまり使わない気もしますね(;´瓜`)
Bridgeについて考えてみる
いつものごとくいい例が思いつきませんが、以下のようなインタフェースがあったとします。
from abc import ABCMeta, abstractmethod class Hoge(metaclass=ABCMeta) : @abstractmethod def functionA(self) : pass
普通にこのインタフェースを使おうとするとこんな感じでしょうか?
class Foo(Hoge) : def functionA(self) : print("機能A")
ここまではよく見かける書き方ですね
では、このインタフェースを実装したクラスに手を加えずに機能拡張して"機能Aを3回実行"するようにしたいと思います。
単純に考えればこんな感じでしょうか?
if __name__ == "__main__" : foo = Foo() for num in range(3): foo.functionA()
これでもよいですがユーザ視点から考えると毎回functionA()を3回実行する処理を書くのは手間ですね。。。
そこで以下のようなクラスを用意します。
class Bar(Hoge) : def __init__(self, hoge): self._hoge = hoge def functionA(self) : for num in range(3): self._hoge.functionA()
これを使えば以下のようにすることができます。
fooインスタンスをそのまま使えば通常機能となり、Barオブジェクトに入れて実行すれば拡張機能となりますね(・`ω´・)v
if __name__ == "__main__" : foo = Foo() foo.functionA() # 通常機能 bar = Bar(foo) bar.functionA() # 拡張機能
サンプルコード
今回はポケモンでピカピカ言っているアイツを倒してみたいと思います(๑◕ܫ◕๑)
このサンプルでは技のダメージをBridgeパターンで"効果抜群だ"と"効果は今ひとつだ"に拡張しています。
# 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 superEffective(Skill): def __init__(self, skill) : self._skill = skill def getDamege(self): print("効果抜群だ!!") return self._skill.getDamege() * 1.5 # 効果は今ひとつクラス class notVeryEffective(Skill): def __init__(self, skill) : self._skill = skill def getDamege(self): print("効果は今ひとつのようだ...") return self._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 = superEffective(skill).getDamege() elif skill.getType() == 'ひこう': damege = notVeryEffective(skill).getDamege() 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 Brigge.py ------------ たいあたり を つかった ------------ かぜおこし を つかった 効果は今ひとつのようだ... ------------ じしん を つかった 効果抜群だ!! ピカチュウ は たおれた め の まえ が まっしろ に なった