Pythonでデザインパターン 捌ノ型「AbstractFactory」
今回はPythonの勉強しながらデザインパターンのAbstractFactoryをやってみました。
他のパターンにつきましては、以下の目次記事をご参照ください。
AbstractFactoryとは
直訳すると「抽象的な工場」になります。
wikiには「関連するインスタンス群を生成するための API を集約することによって、複数のモジュール群の再利用を効率化することを目的とする」とあります。
AbstractFactoryについて考えてみる
突然だが醤油ラーメンを作ろうと思う(・`ω´・;)
# スープを作る soup = Soup(SoySauce()) # 醤油ベース # 麺を作る noodle = Noodle(hardness="H", thickness=5) # 硬め、やや太麺 # トッピングを用意 topping = Topping() topping.add(PorkFillet()) # チャーシュー topping.add(Leek()) # ネギ # ラーメン鉢を用意して盛り付け ramenBowl = RamenBowl() ramenBowl.add(soup) ramenBowl.add(noodle) ramenBowl.add(topping)
一般的な醤油ラーメンの出来上がりだ!
これが一般的な醤油ラーメンかはさておき(・`ω´・;)
でも別の人が作ればこうならないかもしれない。
例えば醤油ベースのスープに豚骨ラーメンのトッピングをしてしまうかも(;^ω^)
# 豚骨ラーメンのトッピングを用意 topping = Topping() topping.add(Tororo()) # とろろ topping.add(Kelp()) # 昆布 topping.add(Bonito()) # かつお節
お客がラーメン鉢の中に好き勝手盛りできるセルフサービスラーメン屋ならいいけれど、
お客からの注文を受けて店員が間違えて盛り付けようならクレーム必至だろう(;゚Д゚)
だから、そうならないようにするために以下のような醤油ラーメンクラスを用意してみました!
class SoySauceRamen(object) : def __init__(self) : # スープ self.soup = Soup(SoySauce()) # 醤油ベース # 麺 self.noodle = Noodle(hardness="H", thickness=5) # トッピング self.topping = Topping() self.topping.add(PorkFillet()) # チャーシュー self.topping.add(Leek()) # ネギ def getSoup(self) -> Soup : return self.soup def getNoodle(self) -> Noodle : return self.noodle def getTopping(self) -> Topping : return self.topping if __name__ == "__main__" : # 醤油ラーメンの元 soySauceRamen = SoySauceRamen() # ラーメン鉢を用意して盛り付け ramenBowl = RamenBowl() ramenBowl.add(soySauceRamen.getSoup()) ramenBowl.add(soySauceRamen.getNoodle()) ramenBowl.add(soySauceRamen.getTopping())
同じように豚骨ラーメンを作るときはまた専用のクラスを用意しておけば材料を間違わないね!!
class PigBonesRamen(object) : def __init__(self) : # 材料準備処理は割愛 def getSoup(self) -> Soup : return self.soup def getNoodle(self) -> Noodle : return self.noodle def getTopping(self) -> Topping : return self.topping if __name__ == "__main__" : pigBonesRamen = PigBonesRamen() # ラーメン鉢を用意して盛り付け ramenBowl = RamenBowl() ramenBowl.add(pigBonesRamen.getSoup()) ramenBowl.add(pigBonesRamen.getNoodle()) ramenBowl.add(pigBonesRamen.getTopping())
ここまでくればお気づきかもですが醤油ラーメンクラスと豚骨ラーメンクラスで共通部分をまとめられそうです。
class RamenBase(metaclass=ABCMeta) : @abstractmethod def getSoup(self) -> Soup : pass @abstractmethod def getNoodle(self) -> Noodle : pass @abstractmethod def getTopping(self) -> Topping : pass
そして以下のようなクラスを用意すればユーザは好きなラーメンの材料を手に入れることができ、盛り付けミスしなくなりますね(・`ω´・)b
class RamenFactory(object) : deg getRamen(ramenType : str) -> RamenBase : if ramenType == "PigBonesRamen" : return PigBonesRamen() elif ramenType == "MisoRamen" : return MisoRamen() elif ramenType == "SaltRamen" : return SaltRamen() else : return SoySauceRamen()
こんな感じがAbstractFactoryだと思っています
サンプルコード
抽象的に書いたのでこのままでは動きませんがサンプルコードです。
class RamenBase(metaclass=ABCMeta) : @abstractmethod def getSoup(self) -> Soup : pass @abstractmethod def getNoodle(self) -> Noodle : pass @abstractmethod def getTopping(self) -> Topping : pass class SoySauceRamen(RamenBase) : # 処理内容は割愛 class PigBonesRamen(RamenBase) : # 処理内容は割愛 class MisoRamen(RamenBase) : # 処理内容は割愛 class SaltRamen(RamenBase) : # 処理内容は割愛 class RamenFactory(object) : deg getRamen(ramenType : str) -> RamenBase : if ramenType == "PigBonesRamen" : return PigBonesRamen() elif ramenType == "MisoRamen" : return MisoRamen() elif ramenType == "SaltRamen" : return SaltRamen() else : return SoySauceRamen() if __name__ == "__main__" : # ラーメン工場を設立 ramenFactory = RamenFactory() # 豚骨ラーメンの注文が入ったら? ramen = ramenFactory.getRamen("PigBonesRamen") # ラーメン鉢を用意して盛り付け ramenBowl = RamenBowl() ramenBowl.add(ramen.getSoup()) ramenBowl.add(ramen.getNoodle()) ramenBowl.add(ramen.getTopping()) # へい、お待ち!!
- 価格: 2948 円
- 楽天で詳細を見る