您使用代理/外观对象来保存对实际对象的引用,如果您愿意,可以使用 self,并且该代理(比外观更好,但现在不更改我的代码)是您代码库的其余部分所看到的.但是,任何属性/方法访问都会转发到可交换的实际对象。
下面的代码应该给你一个粗略的想法。请注意,您需要小心围绕__the_instance 的递归,这就是我直接分配给__dict__ 的原因。有点乱,因为我已经编写了完全包装 getattr 和 setattr 的代码。
class Facade:
def __init__(self, instance):
self.set_obj(instance)
def set_obj(self, instance):
self.__dict__["__theinstance"] = instance
def __getattr__(self, attrname):
if attrname == "__theinstance":
return self.__dict__["__theinstance"]
return getattr(self.__dict__["__theinstance"], attrname)
def __setattr__(self, attrname, value):
if attrname == "__theinstance":
self.set_obj(value)
return setattr(self.__dict__["__theinstance"], attrname, value)
class Test:
def __init__(self, name, cntr):
self.name = name
self.cntr = cntr
def __repr__(self):
return "%s[%s]" % (self.__class__.__name__, self.__dict__)
obj1 = Test("first object", 1)
obj2 = Test("second", 2)
obj2.message = "greetings"
def pretend_client_code(facade):
print(id(facade), facade.name, facade.cntr, getattr(facade, "value", None))
facade = Facade(obj1)
pretend_client_code(facade)
facade.set_obj(obj2)
pretend_client_code(facade)
facade.value = 3
pretend_client_code(facade)
facade.set_obj(obj1)
pretend_client_code(facade)
输出:
4467187104 first object 1 None
4467187104 second 2 None
4467187104 second 2 3
4467187104 first object 1 None
所以基本上,“客户端代码”总是看到相同的外观对象,但它实际访问的内容取决于您的 def b 等效项所做的工作。
Facade 在设计模式术语中具有特定的含义,在这里它可能并不真正适用,但足够接近。也许代理会更好。
请注意,如果您想更改 same 对象上的类,那是另一回事,通过分配 self.__class__ 来完成。例如,假设一个 RPG 游戏的 EnemyClass 一旦被杀死就会被换成 DeadEnemyClass:self.__class__ = DeadEnemyClass