LoginSignup
3
9

More than 3 years have passed since last update.

Pythonで、デザインパターン「Adapter」を学ぶ

Last updated at Posted at 2020-01-16

GoFのデザインパターンを学習する素材として、書籍「増補改訂版Java言語で学ぶデザインパターン入門」が参考になるみたいですね。ただ、取り上げられている実例は、JAVAベースのため、自分の理解を深めるためにも、Pythonで同等のプラクティスに挑んでみました。

■ Adapter(アダプター・パターン)

Adapterパターン(アダプター・パターン)とは、GoF (Gang of Four; 4人のギャングたち) によって定義されたデザインパターンの1つである。Adapterパターンを用いると、既存のクラスに対して修正を加えることなく、インタフェースを変更することができる。Adapterパターンを実現するための手法として"継承を利用した手法"と"委譲を利用した手法"が存在する。

UML class diagram

W3sDesign_Adapter_Design_Pattern_UML.jpg

1. 継承を利用したAdapter

継承を利用したAdapterは、利用したいクラスのサブクラスを作成し、そのサブクラスに対して必要なインタフェースを実装することで実現される。
inheritence.png

2. 委譲を利用したAdapter

委譲を利用したAdapterは、利用したいクラスのインスタンスを生成し、そのインスタンスを他クラスから利用することで実現される。
delegation.png
(以上、ウィキペディア(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クラスが、この役を努めます。

adapter/print.py
from abc import ABCMeta, abstractmethod

class Print(metaclass=ABCMeta):
    @abstractmethod
    def printWeak(self):
        pass

    @abstractmethod
    def printStrng(self):
        pass

(2) Client(依頼者)の役

Target役のメソッドを使って、仕事をする役です。
サンプルプログラムでは、startMainメソッドが、この役を努めます。

Main.py
from adapter.print_banner import PrintBanner

def startMain():
    p = PrintBanner("Hello")
    p.printWeak()
    p.printStrng()

if __name__ == '__main__':
    startMain()

(3) Adaptee(適合される側)の役

Adapter役のなかで実際に動作するメソッドを、ここで実装します。
サンプルプログラムでは、Bannerクラスが、この役を努めます。

adapter/banner.py
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パターンを実現するための手法として、次の二つの手法が存在します。

  • 継承を利用した手法
  • 委譲を利用した手法

□ 継承を利用したサンプルプログラム

adapter/print_banner.py
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()

□ 委譲を利用したサンプルプログラム

adapter/print_banner.py
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()

■ 参考URL

3
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
9