Python模板设计模式中有关重写模板方法的问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python模板设计模式中有关重写模板方法的问题相关的知识,希望对你有一定的参考价值。
我违反了Python中的模板设计模式吗?
因此,我有一个用于创建模板方法的基类,我想创建另外两个可用于执行正常函数返回和生成器函数产生的类?
我不得不重写do_something方法并将语句从“ return”更改为关键字“ yield”,或者我应该做另一种替代设计代码更改?
from abc import ABC, abstractmethod
class BaseClass(ABC):
def do_something(self):
x = self.do_step1()
y = self.do_step2()
return x + y
@abstractmethod
def do_step1(self):
pass
@abstractmethod
def do_step2(self):
pass
class ReturnClass(BaseClass):
def do_something(self):
x = self.do_step1()
y = self.do_step2()
return x + y
def do_step1(self):
return 1
def do_step2(self):
return 1
class YieldClass(BaseClass):
def do_something(self):
x = self.do_step1()
y = self.do_step2()
yield x + y
def do_step1(self):
return 2
def do_step2(self):
return 2
class ConcreteReturnClass(ReturnClass):
def do_step1(self):
return 3
def do_step2(self):
return 3
class ConcreteYieldClass(YieldClass):
def do_step1(self):
return 4
def do_step2(self):
return 4
if __name__ == '__main__':
return_class = ConcreteReturnClass();
print(return_class.do_something())
yield_class = ConcreteYieldClass();
print(next(yield_class.do_something()))
我的目标是创建一个基类作为模板,但我想重用同一类,并将实现方式从仅返回一个关键字更改为产生生成器函数的方式。我认为我违反了该原则,但我找不到可行的替代方法。
在类BaseClass
中,do_something
将是您的模板方法,即,它“根据子类重写以提供具体行为的抽象操作定义算法”。在这种情况下,这些操作由抽象方法do_step1
和do_step2
提供,它们需要被子类覆盖。
但在子类ReturnClass
中,您已经覆盖了模板方法do_something
本身。尽管不被禁止,但是这并不常见。但是在这种情况下,您提供的实现似乎与基类中的实现相同,因此此操作无法完成。我不知道您为什么说您“必须重写do_something方法。”
x = ReturnBase(): print(x.do_something()) // prints 2
无论是否覆盖2
,以上打印do_something
都是ReturnClass
如果您提供了相同的定义。
但是我看到的真正问题是:类或接口代表合同。对于每种方法,都有隐含的前提条件,必须先执行这些条件才能进行调用。对于实现stack
并具有pop
操作的类,调用pop
之前的先决条件是,堆栈中必须至少包含一个元素才能使操作成功。同样,每个方法调用都有一个隐含的后置条件。在最后一个示例中,承诺的是pop
方法将使堆栈中的项比调用前少一个。当子类重写基类方法时,它必须遵守隐含的约定,因为它不需要对方法调用提出更强的先决条件,也不承诺在方法返回时提供更少的条件。
在您的示例中,您有两个子类,它们的do_something
方法返回的结果类型完全不同。这是对Liskov substitution principle的根本违反,该声明指出,如果S是T的子类型,则可以用S类型的对象替换T类型的对象。而YieldClass
类型的对象可能是T的subclass BaseClass
,它不是BaseClass
的subtype,因为do_something_1
(以及BaseClass
中)的方法ReturnClass
返回int
,而do_something_1
中的方法YieldClass
返回发电机。类YeldClass
违反了其基类的约定,并且是非常差的面向对象设计。
以上是关于Python模板设计模式中有关重写模板方法的问题的主要内容,如果未能解决你的问题,请参考以下文章