模板方法 - Python设计模式
Template 方法是一种行为设计模式,它定义了操作的框架,并将细节留给子类实现。它的子类可以根据需要覆盖方法实现,但调用方式与抽象类定义的方式相同。它是行为设计模式中最容易理解和实现的一种。这样的方法在框架开发中被高度使用,因为它们允许我们通过进行某些更改在不同的地方重用单段代码。这也可以避免代码重复。
不使用模板方法的问题
想象一下,您作为软件开发人员正在开发一个Chatbot 应用程序,该应用程序使用数据挖掘技术来分析公司文档的数据。最初,您的应用程序仅适用于数据的 pdf 版本,但后来您的应用程序还需要从其他格式(例如XML 、 CSV等)收集和转换数据。在为其他格式也实现了整个场景之后,您注意到所有类都有很多相似的代码。分析和处理等部分代码在几乎所有类中都是相同的,而在处理数据方面却有所不同。
使用模板方法的解决方案
让我们讨论使用模板方法解决上述问题的方法。它建议将代码分解为一系列步骤,并将这些步骤转换为方法,并将系列调用放在 template_function 中。因此,我们分别创建了template_function并创建了get_xml 、 get_pdf和get_csv等方法来分别处理代码。
Python3
""" method to get the text of file"""
def get_text():
return "plain_text"
""" method to get the xml version of file"""
def get_xml():
return "xml"
""" method to get the pdf version of file"""
def get_pdf():
return "pdf"
"""method to get the csv version of file"""
def get_csv():
return "csv"
"""method used to convert the data into text format"""
def convert_to_text(data):
print("[CONVERT]")
return "{} as text".format(data)
"""method used to save the data"""
def saver():
print("[SAVE]")
"""helper function named as template_function"""
def template_function(getter, converter = False, to_save = False):
"""input data from getter"""
data = getter()
print("Got `{}`".format(data))
if len(data) <= 3 and converter:
data = converter(data)
else:
print("Skip conversion")
"""saves the data only if user want to save it"""
if to_save:
saver()
print("`{}` was processed".format(data))
"""main method"""
if __name__ == "__main__":
template_function(get_text, to_save = True)
template_function(get_pdf, converter = convert_to_text)
template_function(get_csv, to_save = True)
template_function(get_xml, to_save = True)
输出
Got `plain_text`
Skip conversion
[SAVE]
`plain_text` was processed
Got `pdf`
[CONVERT]
`pdf as text` was processed
Got `csv`
Skip conversion
[SAVE]
`csv` was processed
类图
以下是模板方法的类图
好处
- 等效内容:很容易考虑超类中的重复代码,只需将其拉到您想要使用的地方即可。
- 灵活性:它提供了极大的灵活性,使得子类能够决定如何实现算法的步骤。
- 继承的可能性:我们可以重用我们的代码,因为模板方法使用继承提供了代码可重用的能力。
缺点
- 复杂代码:代码有时可能在使用模板方法时变得足够复杂,以至于即使是编写代码的开发人员也很难理解代码。
- 限制:客户可能会要求扩展版本,因为有时他们觉得提供的框架中缺少算法。
- 违规:有可能通过使用模板方法,您最终可能会违反Liskov 替换原则,这绝对不是一件好事。
适用性
- 客户扩展:当您想让客户使用特定步骤而不是算法的整个结构来扩展算法时,总是首选使用此方法。
- 相似算法:当你有很多相似的算法,但有细微的变化时,使用模板设计模式总是更好,因为如果算法发生了一些变化,那么你不必在每个算法中都进行更改。
- 框架开发:强烈建议在开发框架时使用模板设计模式,因为它可以帮助我们避免重复代码以及通过进行某些更改来一次又一次地重用一段代码。
进一步阅读 – Java中的模板方法