<一覧に戻る

プロキシパターン

プロキシパターンは、オブジェクトへのアクセスを制御するためのデザインパターンです。具体的には、対象となるオブジェクトの代理(プロキシ)を作成し、実際のオブジェクトへのアクセスを管理します。このパターンは、リソースの管理や遅延初期化、アクセス制御などに利用されます。

プロキシパターンの構成要素

プロキシパターンは、通常以下の3つの主要なコンポーネントから構成されます。

  1. サブジェクト(Subject): 実際のオブジェクトが実装するインターフェース。
  2. リアルサブジェクト(RealSubject): 実際の処理を行うオブジェクト。
  3. プロキシ(Proxy): リアルサブジェクトへのアクセスを制御する代理オブジェクト。

サンプルコードの実装

以下に、プロキシパターンの簡単な実装例を示します。この例では、画像を表示するためのリアルサブジェクトと、そのリアルサブジェクトへのアクセスを制御するプロキシを作成します。

ステップ1: サブジェクトインターフェースの定義

まず、サブジェクトインターフェースを定義します。これは、リアルサブジェクトとプロキシの両方が実装するインターフェースです。

from abc import ABC, abstractmethod

class Image(ABC):
    @abstractmethod
    def display(self):
        pass

ここでは、Imageという抽象クラスを定義し、displayメソッドを持たせています。このメソッドは、画像を表示するためのものです。

ステップ2: リアルサブジェクトの実装

次に、実際の画像を表すリアルサブジェクトを実装します。

class RealImage(Image):
    def __init__(self, filename: str):
        self.filename = filename
        self.load_image_from_disk()

    def load_image_from_disk(self):
        print(f"Loading {self.filename}")

    def display(self):
        print(f"Displaying {self.filename}")

RealImageクラスは、画像ファイル名を受け取り、画像をディスクから読み込む処理を行います。load_image_from_diskメソッドは、画像が読み込まれたことを示すメッセージを表示します。displayメソッドでは、画像を表示する処理を行います。

ステップ3: プロキシの実装

次に、プロキシクラスを実装します。プロキシは、リアルサブジェクトへのアクセスを制御します。

class ProxyImage(Image):
    def __init__(self, filename: str):
        self.filename = filename
        self.real_image = None

    def display(self):
        if self.real_image is None:
            self.real_image = RealImage(self.filename)
        self.real_image.display()

ProxyImageクラスは、リアルサブジェクトを持っており、displayメソッドでリアルサブジェクトがまだ作成されていない場合にのみ、リアルサブジェクトのインスタンスを生成します。これにより、遅延初期化が実現され、必要なときにのみリソースが消費されます。

ステップ4: 使用例

最後に、これらのクラスを使用してプロキシパターンの効果を確認します。

def main():
    image1 = ProxyImage("image1.jpg")
    image2 = ProxyImage("image2.jpg")

    # 最初の表示では画像をディスクから読み込む
    image1.display()
    print("")

    # 2回目の表示では再度読み込まない
    image1.display()
    print("")

    # 2つ目の画像を初めて表示する
    image2.display()

if __name__ == "__main__":
    main()

コードの解説

  • main関数で、2つのプロキシ画像image1image2を作成します。
  • image1.display()を呼び出すと、プロキシはリアルサブジェクトを生成し、画像をディスクから読み込む処理が行われます。
  • 2回目のimage1.display()呼び出しでは、既にリアルサブジェクトが生成されているため、再度ディスクから読み込むことはありません。
  • image2.display()を呼び出すと、image2のために新しいリアルサブジェクトが生成され、画像がディスクから読み込まれます。

まとめ

プロキシパターンは、オブジェクトへのアクセスを制御し、リソースを効率的に管理するための強力な手法です。上記の例のように、遅延初期化やキャッシング、アクセス制御などに利用されることが多いです。プロキシパターンを使うことで、システムのパフォーマンスを向上させることができます。

出力結果: