週末!プログラミング部

ソフトウェア開発ネタを中心に自分でいろいろ調べた内容を自分の勝手な解釈で思うがままに書いくためのブログ。サンプルソースコード、API、プラットフォーム、プログラミング言語、開発環境などを調査、分析して追求いく予定です。

Pythonでデザインパターン 弐ノ型「Adapter」

今回はPythonの勉強しながらデザインパターンのAdapterをやってみました。
他のパターンにつきましては、以下の目次記事をご参照ください。

Adapterとは

直訳すると「適合させるもの」という意味になりますが、
直訳だと少しわかりにくいですね(;´Д`)
wikiには「既存のクラスに対して修正を加えることなく、インタフェースを変更することができる」とあります。

Adapterについて考えてみる

アダプタと言われると、身近なものではACアダプタが思いつきます。
ACアダプタはコンセントからとったAC(交流)をDC(直流)に変換し、電子機器に電源を供給するための装置です。
このことからアダプタとは、何かからの入力を、変換して、別の何かで使えるようにするための仲介役であると捉えることができますね。

デザインパターンにおけるAdapterパターンもこの考え方を当てはめると、
クラスAがクラスBを使用したい場合、AとBの仲介役として、Bからの入出力を吸収(変換)して、AにBの機能を提供するためのパターンという感じです。

サンプルプログラム

AdapterパターンをPythonで実装してみました。
この例ではHumanクラスのStudentインタフェースでラップしたAdapterを作っています。
Adapterパターンの実現方法には継承を利用するパターンと委譲を利用するパターンがあります。

HumanAdapterクラスは継承を利用するパターンです。
こちらはHumanクラスを継承しています。
そしてStudentインタフェースshowName()とshowAge()を実装するために、親クラスであるHumanクラスのprintName()とprintAge()を呼び出しています。

一方、HumanAdapter2クラスは委譲を利用するパターンです。
こちらはコンストラクタ内でHumanクラスのインスタンスを作成しています。
そしてStudentインタフェースshowName()とshowAge()を実装するために、HumanクラスのインスタンスのprintName()とprintAge()を呼び出しています。

# coding: utf-8

from abc import ABC, ABCMeta, abstractmethod

class Human(object) :
    
    def __init__(self, name, age) :
        self.__name = name
        self.__age = age

    def printName(self) :
        print(self.__name)

    def printAge(self) :
        print(self.__age)

class Student(metaclass=ABCMeta) :

    @abstractmethod
    def showName() :
        pass

    @abstractmethod
    def showAge() :
        pass

class HumanAdapter(Human, Student) :

    def __init__(self, name, age) :
        Human.__init__(self, name, age)

    def showName(self):
        self.printName()

    def showAge(self) :
        self.printAge()

class HumanAdapter2(Student) :

    def __init__(self, name, age) :
        self.__human = Human(name, age)

    def showName(self):
        self.__human.printName()

    def showAge(self) :
        self.__human.printAge()

if __name__ == "__main__" :

    obj = HumanAdapter("AAA", 123)
    obj.showName()
    obj.showAge()
    
    obj2 = HumanAdapter2("BBB", 987)
    obj2.showName()
    obj2.showAge()

実行結果は以下のとおりです!
継承でも委譲でもAdapterの使い方は同じです。

$ python Adapter.py
AAA
123
BBB
987