プロキシパターンは、オブジェクトへのアクセスを制御するためのデザインパターンです。具体的には、対象となるオブジェクトの代理(プロキシ)を作成し、実際のオブジェクトへのアクセスを管理します。このパターンは、リソースの管理や遅延初期化、アクセス制御などに利用されます。
プロキシパターンは、通常以下の3つの主要なコンポーネントから構成されます。
以下に、プロキシパターンの簡単な実装例を示します。この例では、画像を表示するためのリアルサブジェクトと、そのリアルサブジェクトへのアクセスを制御するプロキシを作成します。
まず、サブジェクトインターフェースを定義します。これは、リアルサブジェクトとプロキシの両方が実装するインターフェースです。
from abc import ABC, abstractmethod
class Image(ABC):
@abstractmethod
def display(self):
pass
ここでは、Image
という抽象クラスを定義し、display
メソッドを持たせています。このメソッドは、画像を表示するためのものです。
次に、実際の画像を表すリアルサブジェクトを実装します。
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
メソッドでは、画像を表示する処理を行います。
次に、プロキシクラスを実装します。プロキシは、リアルサブジェクトへのアクセスを制御します。
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
メソッドでリアルサブジェクトがまだ作成されていない場合にのみ、リアルサブジェクトのインスタンスを生成します。これにより、遅延初期化が実現され、必要なときにのみリソースが消費されます。
最後に、これらのクラスを使用してプロキシパターンの効果を確認します。
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つのプロキシ画像image1
とimage2
を作成します。image1.display()
を呼び出すと、プロキシはリアルサブジェクトを生成し、画像をディスクから読み込む処理が行われます。image1.display()
呼び出しでは、既にリアルサブジェクトが生成されているため、再度ディスクから読み込むことはありません。image2.display()
を呼び出すと、image2
のために新しいリアルサブジェクトが生成され、画像がディスクから読み込まれます。プロキシパターンは、オブジェクトへのアクセスを制御し、リソースを効率的に管理するための強力な手法です。上記の例のように、遅延初期化やキャッシング、アクセス制御などに利用されることが多いです。プロキシパターンを使うことで、システムのパフォーマンスを向上させることができます。