LoginSignup
0
1

More than 3 years have passed since last update.

[読書記録]Adapter Pattern

Posted at

Chap2 Adapter Pattern

Adapterパターンとは

  • adapter:提供側と利用側の間に入り、両者をつなぐ(値を変換する)役割
    • 電流の例であれば、「交流200ボルト」(提供側)と「直流12ボルト」(利用側)をつなぐACアダプターのようなもの
  • Adapterパターンには2種類存在する
    • パターン1:クラスによるAdapter(継承を利用する)
    • パターン2:インスタンスによるAdapter(委譲を利用する)

どんなときに使えるのか

  • すでに提供されている(実装されているクラス)のメソッドがそのままでは使えない時や使いづらい時に利用する
  • 既存のクラスを継承もしくは委譲で利用するためすでに実装されている部分はテストしなくてすむ(テスト工数が減る)
  • 既存のコードの書き換え(破壊的変更)をせずに機能を拡張できる

パターン1 クラスによるAdapter(継承を利用する)

2019-10-14-22-19-25.png

Bannerクラス

  • インスタンス生成時に表示する文字列をパラメータとして受ける
  • メソッドによって表示するパターンが異なる
Banner
class Banner():
    def __init__(self, string):
        self._string = string
    def show_with_pattern(self):
        print("({})".format(self._string))
    def show_with_aster(self):
        print("*{}*".format(self._string))

Printインタフェース

  • Mainクラスが利用するインタフェース
printインタフェース
class Print(metaclass=ABCMeta):
    @abstractclassmethod
    def print_weak(self):
        pass
    @abstractclassmethod
    def print_strong(self):
        pass

PrintBannerクラス

  • Bannerクラスを継承する
  • showWithParenメソッドおよびshowWithAsterメソッドを拡張する
PrintBanner
class PrintBanner(Banner, Print):
    def __init__(self, string):
        Banner.__init__(string)
    def print_weak(self):
        self.show_with_paren()
    def print_strong(self):
        self.show_with_aster()

Main

  • PrintBannerインスタンスを作成し、文字列を表示するだけ
  • Bannerクラスのメソッド「show_with_paren」「show_with_aster」がmainメソッドから隠蔽されている
Main
def main():
    p = PrintBanner("Hello")
    p.print_weak()
    p.print_strong()

実行結果

実行結果
Air% python adapter_pattern.py
(Hello)
*Hello*

パターン2 委譲を使ったパターン

  • PrintBannerクラスのフィールドにBannerインスタンスが含まれる
  • PrintBannerクラスはprintWeakメソッドが呼ばれた時に、Bannerクラスに実際の処理を委譲する
    • 具体的な処理はBannerに任せる

2019-10-14-22-42-51.png

Printクラス

  • 継承を利用するパターンではインタフェースで宣言しているが、委譲ではクラスとして宣言する
    • PrintBannerクラスが継承する

コード全体

委譲を使ったパターン
from abc import ABCMeta, abstractclassmethod

class Banner():
    def __init__(self, string):
        self._string = string
    def show_with_paren(self):
        print("({})".format(self._string))
    def show_with_aster(self):
        print("*{}*".format(self._string))

class Print(metaclass=ABCMeta):
    @abstractclassmethod
    def print_weak(self):
        pass
    @abstractclassmethod
    def print_strong(self):
        pass

class PrintBanner(Print):
    def __init__(self, string):
        self._banner = Banner(string)
    def print_weak(self):
        self._banner.show_with_paren()
    def print_strong(self):
        self._banner.show_with_aster()

def main():
    p = PrintBanner("Hello")
    p.print_weak()
    p.print_strong()


if __name__ == "__main__":
    main()

所感

  • すでに作られているプログラムや前バージョンのAPIを拡張する場合に利用できると考える
    • 既存コードを変更せずに機能拡張できるところが大きい
0
1
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
0
1