Proxyパターン (3) - 仮想Proxy

Rubyによるデザインパターン』(ラス・オルセン著 ピアソン・エデュケーション刊)の例をPythonに変換して書いています。目次


最後に、オブジェクトの生成を出来るだけ遅らせ、しかもそれをユーザーに気づかせない、仮想Proxyを作ります。



class VirtualAccountProxy(object):
    """「銀行口座」クラスの仮想Proxy"""
    
    def __init__(self, starting_balance):
        self._subject = None
        self.starting_balance  = starting_balance
    
    def subject(self):
        if self._subject is None:
            self._subject = BankAccount(self.starting_balance)
        return self._subject
    
    def deposit(self, *a, **kw):
        return self.subject().deposit(*a, **kw)
    
    def withdraw(self, *a, **kw):
        return self.subject().withdraw(*a, **kw)
    
    def balance(self, *a, **kw):
        return self.subject().balance(*a, **kw)
    
if __name__ == "__main__":
    proxy_list = []
    for i in xrange(100000):
        proxy_list.append(VirtualAccountProxy(100))
    
    #しばらくしてから・・・
    proxy = proxy_list.pop()
    proxy.deposit(50)
    proxy.withdraw(10)


これで、いくつもVirtualAccountProxyを作ったとしても、


実際に必要になるまでBankAccountは生成されないので、
パフォーマンスを向上させることができます。


ところでこの例では、BankAccountの生成方法はVirtualAccountProxyの責任です。


これでは、BankAccountとVirtualAccountProxyの間の結合度を増してしまいます。


そこで、Strategyパターンを併用します。

class VirtualAccountProxy(object):
    def __init__(self, creation_callable):
        self._subject = None
        self.creation_callable  = creation_callable
    
    def subject(self):
        if self._subject is None:
            self._subject = creation_callable()
        return self._subject
    
    #以下同様


BankAccountの生成はcreation_callableに委譲します。



ProxyパターンはAdapterパターンに良く似ています。

どちらも他のオブジェクトのためのパターンです。

しかし、Adapterがオブジェクトのインターフェイスを変更するのに対し、

Proxyはオブジェクトへのアクセスを制御します。