您的位置 首页 编程知识

Python:重构模式

摄影:帕特里克·何 言简意赅版:这份Python代码表列出了代码坏味道及其对应的设计模式解决方案。 class…

Python:重构模式

摄影:帕特里克·何

言简意赅版:这份Python代码表列出了代码坏味道及其对应的设计模式解决方案。

class 代码坏味道:     代码重复 = [         组合方法,         工厂方法创建多态对象,         链式构造器,         组合替代单多关系,         提取组合,         适配器统一接口,         引入空对象,     ]     方法过长 = [         组合方法,         将累加移至收集参数,         命令替代条件派发器,         将累加移至访问者,         策略替代条件逻辑,     ]     条件复杂 = [  # 复杂的条件逻辑         策略替代条件逻辑,         装饰器修饰,         状态替代改变状态的条件语句,         引入空对象,     ]     基本类型偏执 = [         类替代类型码,         状态替代改变状态的条件语句,         策略替代条件逻辑,         组合替代隐式树,         解释器替代隐式语言,         装饰器修饰,         构建器封装组合,     ]     信息泄露 = [工厂封装类]     解决方案分散 = [将创建知识移至工厂]     接口不同类相似 = 适配器统一接口     类职责过轻 = [内联单例]     类过大 = [         命令替代条件派发器,         状态替代改变状态的条件语句,         组合替代隐式树,     ]     switch语句 = [  # 复杂的switch语句         命令替代条件派发器,         将累加移至访问者,     ]     组合爆炸 = [解释器替代隐式语言]     解决方案奇特 = [适配器统一接口]
登录后复制

代码重构

历时近一年,我终于完成了用Python实现Joshua Kerievsky的《重构到模式》一书中所有重构示例的目标。此书极大地提升了我理解如何在生产代码中应用设计模式的能力。

每个示例都包含对原始代码及其背景的简要描述,随后是重构后的代码以及重构带来的好处。例如,“组合方法”重构将难以理解的代码转化为简洁易懂的实现。

让我们来看一个示例,分析原始代码:

立即学习“”;

# 原始代码 # 代码难以理解 def add(element):     readonly = False     size = 0     elements = []     if not readonly:         new_size = size + 1         if new_size > len(elements):             new_elements = []             for i in range(size):                 new_elements[i] = elements[i]             elements = new_elements         size += 1         elements[size] = element
登录后复制

可见,这段代码难以理解,包含许多嵌套条件和循环。现在来看重构后的代码:

# 重构后的代码 # 新代码使用更有意义的名称,避免嵌套。 # 组合方法重构简化了代码。 def at_capacity(new_size, elements):     return new_size > len(elements)   def grow(size):     new_elements = [None] * size     for i in range(size):         new_elements[i] = elements[i]     return new_elements   def add_elements(elements, element, size):     size += 1     elements[size] = element     return size   def add_refac(element):     readonly = False     if readonly:         return     size = 0     elements = []     new_size = size + 1     if at_capacity(new_size, elements):         elements = grow(size)     size = add_elements(elements, element, size) 
登录后复制

重构的核心思想是使用更有意义的方法来降低复杂度并消除嵌套分支。注意,需要将代码块提取到方法中。

在阅读并编写这些示例的过程中,我需要解释UML图并深入理解其机制。这需要高度的专注力和脑力劳动。很多时候,我不得不从头开始重建示例,因为将代码从Java转换为Python并非易事。Python原生不支持循环导入、构造函数重载或接口,因此需要一些调整。我在这些地方添加了注释,以便将来参考。

通过这个过程,我意识到之前对设计模式的理解大多停留在理论层面,仅限于简单的场景。例如,虽然我理解“多态性”解决了开发问题,但这本书通过抽象设置阶段并重用剩余的测试实现,展示了其在测试自动化中的应用。

以下是两个版本的代码。原始代码和新代码的在于测试的设置。

# 原始代码 # 类似的方法在对象实例化方面有所不同。 # 其他部分相同 class testcase:     pass   class dombuilder:     def __init__(self, orders) -> None:         pass      def calc(self):         return 42   class xmlbuilder:     def __init__(self, orders) -> None:         pass      def calc(self):         return 42   class domtest(testcase):     def run_dom_test(self):         expected = 42         builder = dombuilder("orders")  # 创建不同的对象         assert builder.calc() == expected   class xmltest(testcase):     def run_xml_test(self):         expected = 42         builder = xmlbuilder("orders")  # 创建不同的对象         assert builder.calc() == expected   # 重构后的代码 # 两个测试中,唯一不同之处在于dombuilder或xmlbuilder的实例化。 # 创建了一个outputbuilder作为两个类的接口(鉴于Python使用鸭子类型,这并非必要)。 # 在testcase中,引入了一个名为“create_builder”的新方法,由子类实现。 # 这是每个测试类型在运行时执行的步骤。这就是多态性。当执行两个测试(domtest和xmltest)时, # 从“create_builder”返回的实例取决于实现。它可以是dombuilder或xmlbuilder。 class outputbuilder:     def calc(self):         raise NotImplementedError()   class dombuilderrefac(outputbuilder):     def calc(self):         return 42   class xmlbuilderrefac(outputbuilder):     def calc(self):         return 42   class testcaserefac:     def create_builder(self):         raise NotImplementedError()      def run_test(self):         expected = 42         builder = self.create_builder()  # 创建不同的对象         assert builder.calc() == expected   class domtestrefac(testcaserefac):     def create_builder(self) -> outputbuilder:         return dombuilderrefac()   class xmltestrefac(testcaserefac):     def create_builder(self):         return xmlbuilderrefac()   def run():     dom_tc = domtestrefac()     dom_tc.run_test()      xml_tc = xmltestrefac()     xml_tc.run_test() 
登录后复制

“访问者”模式对我来说是最难理解的。在尝试重构之前,我阅读了《设计模式》一书中关于该模式的内容。只有看到原始(未重构的)代码转换为新版本之后,我才意识到该模式并不像最初看起来那么复杂。本质上,该模式将类与其方法解耦。再次,比较两段代码。该模式的实现是“按书本”进行的。

# 原始代码 # TextExtractor包含许多条件来处理节点,例如StringNode # 重构的思想是将逻辑分配到访问者类中   # 接口 class Node:     pass   class LinkTag(Node):     pass   class Tag(Node):     pass   class StringNode(Node):     pass   class TextExtractor:     def extract_text(self, nodes: list[Node]):         result = []         for node in nodes:             if isinstance(node, StringNode):                 result.append("string")             elif isinstance(node, LinkTag):                 result.append("linktag")             elif isinstance(node, Tag):                 result.append("tag")             else:                 result.append("other")         return result   # 重构后的代码 # 接口(访问者) class NodeVisitorRefac:     def visit_link_tag(self, node):         return "linktag"      def visit_tag(self, node):         return "tag"      def visit_string_node(self, node: object):         return "string"   class NodeRefac:     def accept(self, node: NodeVisitorRefac):         pass   class LinkTagRefac(NodeRefac):     def accept(self, node: NodeVisitorRefac):         return node.visit_link_tag(self)   class TagRefac(NodeRefac):     def accept(self, node: NodeVisitorRefac):         return node.visit_tag(self)   class StringNodeRefac(NodeRefac):     def accept(self, node: NodeVisitorRefac):         return node.visit_string_node(self)   # 具体的访问者 class TextExtractorVisitorRefac(NodeVisitorRefac):     def extract_text(self, nodes: list[NodeRefac]):         result = []         for node in nodes:             result.append(node.accept(self))         return result   def run_refac():     # 原始对象调用其方法     result1 = TextExtractor().extract_text([StringNode()])     # 新对象接受访问者     result2 = TextExtractorVisitorRefac().extract_text([StringNodeRefac()])     return result1, result2 
登录后复制

结论

我强烈推荐这本书。当我第一次阅读它时,我发现仅仅通过静态代码示例来掌握概念既枯燥又困难。然而,当你积极地编写代码时,想法会逐渐清晰起来。错误会发生,解决这些错误需要理解基本概念。这个过程将理论转化为实践,并巩固你的知识。

以上就是Python:重构模式的详细内容,更多请关注php中文网其它相关文章!

本文来自网络,不代表四平甲倪网络网站制作专家立场,转载请注明出处:http://www.elephantgpt.cn/6047.html

作者: nijia

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

联系我们

联系我们

18844404989

在线咨询: QQ交谈

邮箱: 641522856@qq.com

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部