Python中对象通信的代理设计模式
内存和时间是处理大型对象时的两个主要挑战。因此,重用这些对象来生成新的引用而不是在每个新请求上创建它们是很重要的。最重要的是,必须在所有代码段完成处理后释放内存。
代理设计模式是实现大对象初始化的最佳方式。它通过创建行为类似于真实对象的代理代理对象将客户端代码与对象分开。在这里,客户端代码与代理类交互——它有一个真实的对象实例。除了对象初始化之外,它还为日志记录、网络连接、访问共享对象、引用计数等提供了最佳解决方案。
使用代理设计模式的一些优点是:
- 它通过使用额外的间接级别来确保分布式、受控或智能访问
- 它通过添加包装器来保护真实对象免受不必要的复杂性影响。
- 避免不恰当的对象实例化并可以优化应用程序的性能
然而,有时,代理模式会增加对象的响应时间——当第一次请求对象时,对象初始化需要更多时间。
执行
让我们实现一个Python代码来实例化一个包含 1000 万位数字的大对象—— RealClass 。由于它持有一个大对象,因此最好使用代理( ProxyClass )与该对象进行交互,而不是发起直接通信。
首先,让我们创建一个抽象类 - AbstractClass - 为 RealClass 和 ProxyClass 提供接口。抽象类有一个方法叫做sort_digits,真正的类继承于抽象类。代理类使用RealClass的实例,方便客户端通信。
Python3
import abc
import random
class AbstractClass(metaclass=abc.ABCMeta):
""" interface for real and proxy object """
@abc.abstractmethod
def sort_digits(self, reverse=False):
pass
class RealClass(AbstractClass):
""" RealClass that holds a larger object """
def __init__(self):
self.digits = []
for i in range(1000000):
self.digits.append(random.random())
def sort_digits(self, reverse=False):
self.digits.sort()
if reverse:
self.digits.reverse()
class ProxyClass(AbstractClass):
""" A proxy class that has the same interface as RealClass. """
ref_count = 0
def __init__(self):
""" Creates an object if it doesn't exist and caches it otherwise """
if not getattr(self.__class__, 'cached_object', None):
self.__class__.cached_object = RealClass()
print('New object generated')
else:
print('Using cached object')
self.__class__.ref_count += 1
print('Reference Count:', self.__class__.ref_count)
def sort_digits(self, reverse=False):
print('Sort method')
print(locals().items())
# invokes the sort_digits method of real class
self.__class__.cached_object.sort_digits(reverse=reverse)
def __del__(self):
""" Delete the object when the number of reference is 0 """
self.__class__.ref_count -= 1
if self.__class__.ref_count == 0:
print('Deleting cached object')
del self.__class__.cached_object
print('Reference Count:', self.__class__.ref_count)
if __name__ == '__main__':
proxA = ProxyClass()
print()
proxB = ProxyClass()
print()
proxC = ProxyClass()
print()
proxA.sort_digits(reverse=True)
print()
print('Deleting proxA')
del proxA
print('Deleting proxB')
del proxB
print('Deleting proxC')
del proxC
输出:
New object generated
Reference Count: 1
Using cached object
Reference Count: 2
Using cached object
Reference Count: 3
Sort method
dict_items([(‘reverse’, True), (‘self’, <__main__.ProxyClass object at 0x7ff50f73e0b8>)])
Deleting proxA
Reference Count: 2
Deleting proxB
Reference Count: 1
Deleting proxC
Deleting cached object
Reference Count: 0
让我们看看 ProxyClass 设计。如果之前没有创建过,它会创建RealClass的一个实例。如果对象已经存在,代理类会增加引用计数并返回到真实类的新链接。而代理类中的 sort 方法调用真实类的 sort 方法,使用缓存的引用。最后,析构函数方法在每次调用时都会减少引用计数,当没有引用时,它会删除对象。
代理设计模式通过缓存常用对象来优化应用程序的性能,并通过检查访问权限来提高应用程序的安全性。除此之外,它还有助于远程系统交互。