HoRain云--Python 工厂模式
HoRain 云小助手个人主页⛺️生活的理想就是为了理想的生活!⛳️ 推荐前些天发现了一个超棒的服务器购买网站性价比超高大内存超划算忍不住分享一下给大家。点击跳转到网站。目录⛳️ 推荐为什么需要工厂模式工厂模式的三种类型1. 简单工厂模式基本结构实例优点与缺点2. 工厂方法模式基本结构实例工厂方法模式流程3. 抽象工厂模式基本结构实例三种工厂模式对比实际应用场景场景 1数据库连接工厂实例场景 2日志记录器工厂实例最佳实践和注意事项1. 何时使用工厂模式2. 常见错误和避免方法实例实例3. 与依赖注入的结合实例练习题目练习 1实现形状工厂练习 2扩展数据库工厂练习 3配置驱动的工厂总结工厂模式是一种创建型设计模式它提供了一种创建对象的最佳方式。想象一下你去餐厅点餐你不需要知道厨房如何制作食物只需要告诉服务员你想要什么厨房就会为你制作出来。工厂模式就是这样一个厨房它负责创建对象而你只需要告诉它你想要什么类型的对象。为什么需要工厂模式在编程中我们经常需要创建对象。如果直接在代码中使用new关键字或类的构造函数会导致代码耦合度高创建对象的代码与具体类紧密绑定维护困难当需要修改或添加新的对象类型时需要修改多处代码违反开闭原则对扩展开放对修改关闭的原则被破坏工厂模式通过将对象的创建过程封装起来解决了这些问题。工厂模式的三种类型工厂模式主要分为三种类型让我们通过具体的例子来理解它们。1. 简单工厂模式简单工厂模式是最基础的工厂模式它通过一个工厂类来创建不同类型的对象。基本结构实例from abc import ABC, abstractmethod# 产品接口class Animal(ABC):abstractmethoddef speak(self):pass# 具体产品class Dog(Animal):def speak(self):return 汪汪class Cat(Animal):def speak(self):return 喵喵class Duck(Animal):def speak(self):return 嘎嘎# 简单工厂class AnimalFactory:staticmethoddef create_animal(animal_type):if animal_type dog:return Dog()elif animal_type cat:return Cat()elif animal_type duck:return Duck()else:raise ValueError(f未知的动物类型: {animal_type})# 使用示例def test_simple_factory():factory AnimalFactory()dog factory.create_animal(dog)cat factory.create_animal(cat)duck factory.create_animal(duck)print(dog.speak()) # 输出: 汪汪print(cat.speak()) # 输出: 喵喵print(duck.speak()) # 输出: 嘎嘎if __name__ __main__:test_simple_factory()优点与缺点优点客户端与具体产品类解耦职责分离易于维护缺点添加新产品需要修改工厂类违反开闭原则工厂类职责过重不符合单一职责原则2. 工厂方法模式工厂方法模式通过让子类决定创建什么对象来解决简单工厂模式的问题。基本结构实例from abc import ABC, abstractmethod# 产品接口class Button(ABC):abstractmethoddef render(self):passabstractmethoddef onClick(self):pass# 具体产品class WindowsButton(Button):def render(self):return 渲染 Windows 风格按钮def onClick(self):return Windows 按钮被点击class MacButton(Button):def render(self):return 渲染 Mac 风格按钮def onClick(self):return Mac 按钮被点击# 创建者抽象类class Dialog(ABC):abstractmethoddef createButton(self) - Button:passdef render(self):# 调用工厂方法创建产品button self.createButton()result button.render()return result# 具体创建者class WindowsDialog(Dialog):def createButton(self) - Button:return WindowsButton()class MacDialog(Dialog):def createButton(self) - Button:return MacButton()# 使用示例def test_factory_method():# 根据配置选择具体的工厂config windows # 可以从配置文件读取if config windows:dialog WindowsDialog()else:dialog MacDialog()result dialog.render()print(result)if __name__ __main__:test_factory_method()工厂方法模式流程3. 抽象工厂模式抽象工厂模式提供一个创建一系列相关或依赖对象的接口而无需指定它们具体的类。基本结构实例from abc import ABC, abstractmethod# 抽象产品 Aclass Button(ABC):abstractmethoddef paint(self):pass# 抽象产品 Bclass Checkbox(ABC):abstractmethoddef paint(self):pass# 具体产品 A1class WindowsButton(Button):def paint(self):return 渲染 Windows 按钮# 具体产品 A2class MacButton(Button):def paint(self):return 渲染 Mac 按钮# 具体产品 B1class WindowsCheckbox(Checkbox):def paint(self):return 渲染 Windows 复选框# 具体产品 B2class MacCheckbox(Checkbox):def paint(self):return 渲染 Mac 复选框# 抽象工厂class GUIFactory(ABC):abstractmethoddef createButton(self) - Button:passabstractmethoddef createCheckbox(self) - Checkbox:pass# 具体工厂 1class WindowsFactory(GUIFactory):def createButton(self) - Button:return WindowsButton()def createCheckbox(self) - Checkbox:return WindowsCheckbox()# 具体工厂 2class MacFactory(GUIFactory):def createButton(self) - Button:return MacButton()def createCheckbox(self) - Checkbox:return MacCheckbox()# 客户端代码class Application:def __init__(self, factory: GUIFactory):self.factory factoryself.button Noneself.checkbox Nonedef createUI(self):self.button self.factory.createButton()self.checkbox self.factory.createCheckbox()def paint(self):result []if self.button:result.append(self.button.paint())if self.checkbox:result.append(self.checkbox.paint())return \n.join(result)# 使用示例def test_abstract_factory():# 根据系统类型选择工厂system_type windows # 可以自动检测或从配置读取if system_type windows:factory WindowsFactory()else:factory MacFactory()app Application(factory)app.createUI()print(app.paint())if __name__ __main__:test_abstract_factory()三种工厂模式对比特性简单工厂模式工厂方法模式抽象工厂模式复杂度低中高扩展性差好很好适用场景对象种类少单一产品族多个相关产品族开闭原则违反遵守遵守依赖关系依赖具体类依赖抽象类依赖抽象接口实际应用场景场景 1数据库连接工厂实例from abc import ABC, abstractmethodimport sqlite3import mysql.connector# 数据库连接接口class DatabaseConnection(ABC):abstractmethoddef connect(self):passabstractmethoddef execute(self, query):pass# 具体数据库连接class SQLiteConnection(DatabaseConnection):def __init__(self, db_path):self.db_path db_pathself.connection Nonedef connect(self):self.connection sqlite3.connect(self.db_path)return self.connectiondef execute(self, query):if self.connection:cursor self.connection.cursor()cursor.execute(query)return cursor.fetchall()class MySQLConnection(DatabaseConnection):def __init__(self, host, user, password, database):self.host hostself.user userself.password passwordself.database databaseself.connection Nonedef connect(self):self.connection mysql.connector.connect(hostself.host,userself.user,passwordself.password,databaseself.database)return self.connectiondef execute(self, query):if self.connection:cursor self.connection.cursor()cursor.execute(query)return cursor.fetchall()# 数据库工厂class DatabaseFactory:staticmethoddef create_connection(db_type, **kwargs):if db_type sqlite:return SQLiteConnection(**kwargs)elif db_type mysql:return MySQLConnection(**kwargs)else:raise ValueError(f不支持的数据库类型: {db_type})# 使用示例def test_database_factory():# 创建 SQLite 连接sqlite_conn DatabaseFactory.create_connection(sqlite,db_pathexample.db)sqlite_conn.connect()# 创建 MySQL 连接mysql_conn DatabaseFactory.create_connection(mysql,hostlocalhost,userroot,passwordpassword,databasetest)mysql_conn.connect()print(数据库连接创建成功)if __name__ __main__:test_database_factory()场景 2日志记录器工厂实例import loggingfrom abc import ABC, abstractmethodimport sys# 日志记录器接口class Logger(ABC):abstractmethoddef info(self, message):passabstractmethoddef error(self, message):passabstractmethoddef debug(self, message):pass# 控制台日志记录器class ConsoleLogger(Logger):def info(self, message):print(fINFO: {message})def error(self, message):print(fERROR: {message}, filesys.stderr)def debug(self, message):print(fDEBUG: {message})# 文件日志记录器class FileLogger(Logger):def __init__(self, filename):self.filename filenamedef info(self, message):with open(self.filename, a) as f:f.write(fINFO: {message}\n)def error(self, message):with open(self.filename, a) as f:f.write(fERROR: {message}\n)def debug(self, message):with open(self.filename, a) as f:f.write(fDEBUG: {message}\n)# 日志工厂class LoggerFactory:staticmethoddef get_logger(logger_type, **kwargs):if logger_type console:return ConsoleLogger()elif logger_type file:return FileLogger(**kwargs)else:raise ValueError(f不支持的日志类型: {logger_type})# 使用示例def test_logger_factory():# 创建控制台日志记录器console_logger LoggerFactory.get_logger(console)console_logger.info(这是一个信息消息)console_logger.error(这是一个错误消息)# 创建文件日志记录器file_logger LoggerFactory.get_logger(file, filenameapp.log)file_logger.info(记录到文件的信息)file_logger.debug(调试信息)if __name__ __main__:test_logger_factory()最佳实践和注意事项1. 何时使用工厂模式适合使用工厂模式的情况创建对象的过程比较复杂需要根据不同的条件创建不同的对象希望将对象的创建与使用分离系统需要支持多种类型的产品不适合使用的情况对象的创建过程很简单直接使用构造函数即可产品类型很少且不太可能扩展2. 常见错误和避免方法错误 1过度设计实例# 不推荐简单情况使用复杂工厂class SimpleObject:def __init__(self, name):self.name name# 过度设计的工厂class SimpleObjectFactory:staticmethoddef create_simple_object(name):return SimpleObject(name)# 推荐直接创建obj SimpleObject(test)错误 2工厂类职责过多实例# 不推荐一个工厂做太多事情class GodFactory:def create_user(self): ...def create_order(self): ...def create_product(self): ...def send_email(self): ... # 这不是创建对象# 推荐按职责分离class UserFactory: ...class OrderFactory: ...class ProductFactory: ...3. 与依赖注入的结合工厂模式经常与依赖注入DI一起使用实例from abc import ABC, abstractmethod# 服务接口class NotificationService(ABC):abstractmethoddef send(self, message):pass# 具体服务class EmailService(NotificationService):def send(self, message):return f发送邮件: {message}class SMSService(NotificationService):def send(self, message):return f发送短信: {message}# 工厂class NotificationFactory:staticmethoddef create_service(service_type):if service_type email:return EmailService()elif service_type sms:return SMSService()else:raise ValueError(f未知的服务类型: {service_type})# 使用依赖注入的类class OrderProcessor:def __init__(self, notification_service: NotificationService):self.notification_service notification_servicedef process_order(self, order):# 处理订单逻辑result self.notification_service.send(订单处理完成)return result# 使用def main():# 通过工厂创建服务notification_service NotificationFactory.create_service(email)# 注入依赖processor OrderProcessor(notification_service)result processor.process_order({id: 1})print(result)if __name__ __main__:main()练习题目练习 1实现形状工厂创建一个形状工厂支持创建圆形Circle、矩形Rectangle和三角形Triangle。每个形状都应该有计算面积和周长的方怯。要求使用工厂方法模式每个形状类实现calculate_area()和calculate_perimeter()方法提供使用示例练习 2扩展数据库工厂基于前面的数据库工厂示例添加对 PostgreSQL 数据库的支持。要求创建PostgreSQLConnection类修改工厂以支持新数据库类型确保不破坏现有代码练习 3配置驱动的工厂创建一个可以根据配置文件动态选择工厂的系统。要求从 JSON 或 YAML 文件读取配置根据配置创建相应的对象支持热更新配置总结工厂模式是 Python 设计中非常重要的创建型模式它通过将对象的创建过程封装起来提供了以下好处降低耦合度客户端不需要知道具体产品的创建细节提高可维护性创建逻辑集中管理易于修改和扩展增强灵活性可以轻松添加新的产品类型促进代码复用创建逻辑可以在多个地方重用记住选择适合的工厂模式类型简单工厂适用于产品类型较少且不太变化的场景工厂方法适用于需要扩展产品族的场景抽象工厂适用于需要创建相关产品族的复杂场景通过合理使用工厂模式你可以编写出更加灵活、可维护和可扩展的 Python 代码❤️❤️❤️本人水平有限如有纰漏欢迎各位大佬评论批评指正如果觉得这篇文对你有帮助的话也请给个点赞、收藏下吧非常感谢! Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧