依赖注入与工厂模式教程(Python示例)
概述
本教程将介绍两种重要的设计模式:依赖注入(Dependency Injection) 和工厂模式(Factory Pattern),并通过Python示例展示它们的实际应用。
- 依赖注入 (Dependency Injection)
1.1 什么是依赖注入?
依赖注入是一种设计模式,通过外部提供对象所需的依赖关系,而不是在对象内部创建它们。这提高了代码的灵活性、可测试性和可维护性。
1.2 示例:没有使用依赖注入
python
class EmailService:
def send_email(self, message):
print(f"Sending email: {message}")
class UserService:
def __init__(self):
self.email_service = EmailService() # 直接创建依赖
def register_user(self, username):
# 用户注册逻辑
self.email_service.send_email(f"Welcome {username}!")
# 使用
user_service = UserService()
user_service.register_user("Alice")
1.3 示例:使用依赖注入
python
class EmailService:
def send_email(self, message):
print(f"Sending email: {message}")
class SMSService:
def send_sms(self, message):
print(f"Sending SMS: {message}")
class UserService:
def __init__(self, notification_service): # 依赖通过参数注入
self.notification_service = notification_service
def register_user(self, username):
# 用户注册逻辑
self.notification_service.send(f"Welcome {username}!")
# 使用依赖注入
email_service = EmailService()
user_service = UserService(email_service)
user_service.register_user("Alice")
# 可以轻松替换实现
sms_service = SMSService()
user_service_sms = UserService(sms_service)
user_service_sms.register_user("Bob")
- 工厂模式 (Factory Pattern)
2.1 什么是工厂模式?
工厂模式是一种创建型设计模式,它提供了一种创建对象的接口,但允许子类决定实例化哪个类。工厂方法让类的实例化推迟到子类。
2.2 简单工厂模式
python
class Dog:
def speak(self):
return "Woof!"
class Cat:
def speak(self):
return "Meow!"
class AnimalFactory:
@staticmethod
def create_animal(animal_type):
if animal_type == "dog":
return Dog()
elif animal_type == "cat":
return Cat()
else:
raise ValueError(f"Unknown animal type: {animal_type}")
# 使用工厂
factory = AnimalFactory()
dog = factory.create_animal("dog")
print(dog.speak()) # 输出: Woof!
cat = factory.create_animal("cat")
print(cat.speak()) # 输出: Meow!
2.3 工厂方法模式
python
from abc import ABC, abstractmethod
# 抽象产品
class Button(ABC):
@abstractmethod
def render(self):
pass
# 具体产品
class WindowsButton(Button):
def render(self):
return "渲染一个Windows风格的按钮"
class WebButton(Button):
def render(self):
return "渲染一个Web风格的按钮"
# 抽象创建者
class Dialog(ABC):
@abstractmethod
def create_button(self) -> Button:
pass
def render(self):
button = self.create_button()
return button.render()
# 具体创建者
class WindowsDialog(Dialog):
def create_button(self) -> Button:
return WindowsButton()
class WebDialog(Dialog):
def create_button(self) -> Button:
return WebButton()
# 使用
dialog = WindowsDialog()
print(dialog.render()) # 输出: 渲染一个Windows风格的按钮
dialog = WebDialog()
print(dialog.render()) # 输出: 渲染一个Web风格的按钮
- 结合依赖注入和工厂模式
3.1 示例:数据库连接工厂与依赖注入
python
from abc import ABC, abstractmethod
# 数据库连接接口
class DatabaseConnection(ABC):
@abstractmethod
def connect(self):
pass
@abstractmethod
def execute_query(self, query):
pass
# 具体实现
class MySQLConnection(DatabaseConnection):
def connect(self):
return "连接到MySQL数据库"
def execute_query(self, query):
return f"在MySQL上执行: {query}"
class PostgreSQLConnection(DatabaseConnection):
def connect(self):
return "连接到PostgreSQL数据库"
def execute_query(self, query):
return f"在PostgreSQL上执行: {query}"
# 连接工厂
class DatabaseConnectionFactory:
@staticmethod
def create_connection(db_type):
if db_type == "mysql":
return MySQLConnection()
elif db_type == "postgresql":
return PostgreSQLConnection()
else:
raise ValueError(f"不支持的数据库类型: {db_type}")
# 使用依赖注入的服务
class UserService:
def __init__(self, db_connection: DatabaseConnection):
self.db_connection = db_connection
self.db_connection.connect()
def get_user(self, user_id):
query = f"SELECT * FROM users WHERE id = {user_id}"
return self.db_connection.execute_query(query)
# 配置和应用
def main():
# 通过工厂创建依赖
db_factory = DatabaseConnectionFactory()
db_connection = db_factory.create_connection("mysql")
# 注入依赖
user_service = UserService(db_connection)
result = user_service.get_user(123)
print(result)
if __name__ == "__main__":
main()
3.2 更高级的依赖注入容器
python
class DIContainer:
def __init__(self):
self._services = {}
self._factories = {}
def register_service(self, name, service):
self._services[name] = service
def register_factory(self, name, factory):
self._factories[name] = factory
def get_service(self, name):
if name in self._services:
return self._services[name]
elif name in self._factories:
return self._factories[name]()
else:
raise ValueError(f"未找到服务或工厂: {name}")
# 使用容器
container = DIContainer()
container.register_factory("db_connection", lambda: DatabaseConnectionFactory().create_connection("mysql"))
container.register_service("user_service", UserService(container.get_service("db_connection")))
# 获取服务
user_service = container.get_service("user_service")
result = user_service.get_user(123)
print(result)
- 总结
· 依赖注入通过外部提供依赖,提高了代码的灵活性和可测试性
· 工厂模式将对象创建逻辑封装起来,使代码更易于维护和扩展
· 结合使用这两种模式可以创建高度可配置和可测试的应用程序
这两种模式是现代软件开发中的重要概念,特别是在构建大型、可维护的应用程序时。