我有以下类使用附加的 DelegatorParent 类实现“委托(delegate)设计模式”:
class DelegatorParent():
def __init__(self):
self.a = 'whatever'
class ConcreteDelegatee():
def myMethod(self):
return 'myMethod'
class Delegator(DelegatorParent):
def __init__(self):
self.delegatee = ConcreteDelegatee()
DelegatorParent.__init__(self)
def __getattr__(self, attrname):
return getattr(self.delegatee, attrname)
a = Delegator()
result = a.myMethod()
一切看起来都很好。
现在我想在 DelegatorParent 中放置一个抽象方法,以确保始终定义“myMethod”。
from abc import ABCMeta, abstractmethod
class DelegatorParent():
__metaclass__ = ABCMeta
@abstractmethod
def myMethod(self):
pass
def __init__(self):
self.a = 'whatever'
class ConcreteDelegatee():
def myMethod(self):
return 'myMethod'
class Delegator(DelegatorParent):
def __init__(self):
self.delegatee = ConcreteDelegatee()
DelegatorParent.__init__(self)
def __getattr__(self, attrname):
return getattr(self.delegatee, attrname)
# This method seems unnecessary, but if I erase it an exception is
# raised because the abstract method's restriction is violated
def myMethod(self):
return self.delegatee.myMethod()
a = Delegator()
result = a.myMethod()
你能帮我找到一种“优雅”的方法来从“Delegator”中删除“myMethod”吗...直觉告诉我它在某种程度上是多余的(考虑到定义了自定义 getattr 方法)。
更重要的是,请注意,在这个实现中,如果我忘记在 ConcreteDelegatee 中定义 myMethod,程序会编译,但如果我调用 Delegator.myMethod(),它可能会在运行时崩溃,这正是我想通过使用来避免的DelegatorParent 中的抽象方法。
显然,一个简单的解决方案是将@abstractmethod 移动到Delegator 类,但我想避免这样做,因为在我的程序中DelegatorParent 是一个非常重要的类(而Delegator 只是一个辅助类)。
最佳答案
您可以决定自动实现委托(delegate)给 ConcreteDelegatee
的抽象方法。
对于每个抽象方法,检查它的名称是否存在于 ConcreteDelegatee
类中,并将此方法作为此类方法的委托(delegate)来实现。
from abc import ABCMeta, abstractmethod
class DelegatorParent(object):
__metaclass__ = ABCMeta
def __init__(self):
self.a = 'whatever'
@abstractmethod
def myMethod(self):
pass
class Delegatee(object):
pass
class ConcreteDelegatee(Delegatee):
def myMethod(self):
return 'myMethod'
def myMethod2(self):
return 'myMethod2'
class Delegator(DelegatorParent):
def __new__(cls, *args, **kwargs):
implemented = set()
for name in cls.__abstractmethods__:
if hasattr(ConcreteDelegatee, name):
def delegated(this, *a, **kw):
meth = getattr(this.delegatee, name)
return meth(*a, **kw)
setattr(cls, name, delegated)
implemented.add(name)
cls.__abstractmethods__ = frozenset(cls.__abstractmethods__ - implemented)
obj = super(Delegator, cls).__new__(cls, *args, **kwargs)
obj.delegatee = ConcreteDelegatee()
return obj
def __getattr__(self, attrname):
# Called only for attributes not defined by this class (or its bases).
# Retrieve attribute from current behavior delegate class instance.
return getattr(self.delegatee, attrname)
# All abstract methods are delegared to ConcreteDelegatee
a = Delegator()
print(a.myMethod()) # correctly prints 'myMethod'
print(a.myMethod2()) #correctly prints 'myMethod2'
这解决了主要问题(防止 ConcreteDelegatee
忘记定义 myMethod
)。如果您忘记实现其他抽象方法,仍会检查它们。
__new__
方法负责委托(delegate),让您的 __init__
有空去做。
关于python - python中具有抽象方法的委托(delegate)设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46677221/