GoFのデザインパターンを学習する素材として、書籍「増補改訂版Java言語で学ぶデザインパターン入門」が参考になるみたいですね。ただ、取り上げられている実例は、JAVAベースのため、自分の理解を深めるためにも、Pythonで同等のプラクティスに挑んでみました。
■ Adapter(アダプター・パターン)
Adapterパターン(アダプター・パターン)とは、GoF (Gang of Four; 4人のギャングたち) によって定義されたデザインパターンの1つである。Adapterパターンを用いると、既存のクラスに対して修正を加えることなく、インタフェースを変更することができる。Adapterパターンを実現するための手法として"継承を利用した手法"と"委譲を利用した手法"が存在する。
UML class diagram
1. 継承を利用したAdapter
継承を利用したAdapterは、利用したいクラスのサブクラスを作成し、そのサブクラスに対して必要なインタフェースを実装することで実現される。
2. 委譲を利用したAdapter
委譲を利用したAdapterは、利用したいクラスのインスタンスを生成し、そのインスタンスを他クラスから利用することで実現される。
(以上、ウィキペディア(Wikipedia)より引用)
■ "Adapter"のサンプルプログラム
実際に、Adapterパターンを活用したサンプルプログラムを動かしてみて、次のような動作の様子を確認したいと思います。
- 文字列を、カッコでくくって表示する
- 文字列の前後に、*印をつけて表示する
$ python Main.py
(Hello)
*Hello*
■ サンプルプログラムの詳細
Gitリポジトリにも、同様のコードをアップしています。
https://github.com/ttsubo/study_of_design_pattern/tree/master/Adapter
- ディレクトリ構成
.
├── Main.py
└── adapter
├── __init__.py
├── banner.py
├── print.py
└── print_banner.py
(1) Target(対象)の役
Target
役は、インスタンスの振る舞いに関わるインタフェースを定めます。
サンプルプログラムでは、Print
クラスが、この役を努めます。
from abc import ABCMeta, abstractmethod
class Print(metaclass=ABCMeta):
@abstractmethod
def printWeak(self):
pass
@abstractmethod
def printStrng(self):
pass
(2) Client(依頼者)の役
Target
役のメソッドを使って、仕事をする役です。
サンプルプログラムでは、startMain
メソッドが、この役を努めます。
from adapter.print_banner import PrintBanner
def startMain():
p = PrintBanner("Hello")
p.printWeak()
p.printStrng()
if __name__ == '__main__':
startMain()
(3) Adaptee(適合される側)の役
Adapter
役のなかで実際に動作するメソッドを、ここで実装します。
サンプルプログラムでは、Banner
クラスが、この役を努めます。
class Banner(object):
def __init__(self, string):
self.__string = string
def showWithParen(self):
print("({0})".format(self.__string))
def showWithAster(self):
print("*{0}*".format(self.__string))
(4) Adapter(適合する側)の役
Adapter
役は、Target
役のインタフェースを実装しているクラスです。
サンプルプログラムでは、PrintBanner
クラスが、この役を努めます。
Adapterパターンを実現するための手法として、次の二つの手法が存在します。
- 継承を利用した手法
- 委譲を利用した手法
□ 継承を利用したサンプルプログラム
from adapter.banner import Banner
from adapter.print import Print
class PrintBanner(Banner, Print):
def __init__(self, string):
super(PrintBanner, self).__init__(string)
def printWeak(self):
self.showWithParen()
def printStrng(self):
self.showWithAster()
□ 委譲を利用したサンプルプログラム
from adapter.banner import Banner
from adapter.print import Print
class PrintBanner(Print):
def __init__(self, string):
self.__banner = Banner(string)
def printWeak(self):
self.__banner.showWithParen()
def printStrng(self):
self.__banner.showWithAster()