Python_面向对象:多态&工厂模式
一、概念
多态是面向对象编程的三大特征之一,多态则是指同一个行为可以有多个不同表现形式的能力。也就是说,在父类中定义的属性和方法,在子类继承后,可以有不同的数据类型或表现出不同的行为。这可以使得同一个属性或方法,在父类及其各个子类中,可能会有不同的表现或含义。
二、作用
根据多态的概念可知,多态机制可以在不修改父类代码的基础上,允许多个子类进行功能的扩展。比如父类中定义了一个方法A,有N个子类继承该父类,这几个子类都可以重写这个A方法。并且子类的方法还可以将自己的参数类型改为父类方法的参数类型,或者将自己的返回值类型改为父类方法的返回值类型。这样就可以动态地调整对象的调用,降低对象之间的依存关系,消除类型之间的耦合,使程序有良好的扩展,并可以对所有类的对象进行通用处理,让代码实现更加的灵活和简洁。
三、实现多态的条件
1、必须在继承体系下
2、子类必须要对父类中的方法进行重写
3、通过子类的引用调用重写的方法
3.1 案例演示
同一目录下有文件如下:
report.py
class BaseReport(object): report_type = None def __init__(self): self.content = None def handle_content(self): pass def write(self): content = self.content or "无报告" print("输出测试报告:" + content) class HtmlReport(BaseReport): report_type = "Html" def handle_content(self): self.content = "处理html报告内容" class TextReport(BaseReport): report_type = "Text" def handle_content(self): self.content = "处理text报告内容" class XmlReport(BaseReport): report_type = "Xml" def handle_content(self): self.content = "处理xml报告内容"
run.py
from report import HtmlReport, TextReport # 简单方式演示多态 def run_test(report_type): if report_type == "Html": obj = HtmlReport() else: obj = TextReport() # 不同的实例对象,使用相同的方法,产生不同的结果,这就是多态的表现 obj.handle_content() obj.write() if __name__ == '__main__': run_test("Html") run_test("Text")
上面的代码通过 run_test 方法传入不同的参数,生成了不同的报告,像这种引用不同的实例对象,调用相同的方法,产生不同的结果,就是多态的表现。
四、工厂模式
再回头看下 run_test 这个方法,如果要添加新的类型报告(比如:xml),就要修改run_test 方法中的if 判断逻辑,这样的代码耦合性很高。那有没有什么方法来解耦呢?答案是使用 工厂模式。
工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。在工厂模式中,对象的创建过程被封装在工厂类中,通过工厂类来创建对象,可以将对象的创建与使用代码分离,提供一种统一的接口来创建不同类型的对象。这样可以降低代码的耦合性,提高代码的可维护性和可扩展性。
4.1 优点
- 降低代码耦合性:通过工厂类创建对象,可以将对象的创建与使用代码分离,降低了代码之间的耦合性,使得代码更加清晰和易于维护。
- 提高代码的可扩展性:如果需要增加新的产品类,只需要增加相应的工厂类和产品类即可,无需修改原有的代码,符合开闭原则,提高了代码的可扩展性。
- 提供统一的接口:工厂模式提供一个共同的接口来创建各种对象,这使得代码更加统一和易于理解。
4.2 工厂模式案例演示
import importlib from report import BaseReport # 工厂模式演示多态 def factory_run_test(report_type): # 导入report.py模块 mod = importlib.import_module("report") func_strs = dir(mod) for fs in func_strs: cur_func = getattr(mod, fs) # 判断模块是否是类 if not isinstance(cur_func, type): continue # 判断模块是否是BaseReport的子类 if not issubclass(cur_func, BaseReport): continue if cur_func.report_type == report_type: obj = cur_func() obj.handle_content() obj.write() break else: print("未知报告类型") if __name__ == '__main__': factory_run_test("Html") factory_run_test("Text") factory_run_test("Xml")
从代码以及执行情况可以看出,如果添加新的类型报告,只需要按规范添加BaseReport子类即可,不需要再修改 factory_run_test 方法的代码。