【设计模式】策略类和依赖注入

工作原因由c++切换到python,语法有一些不一样的地方,记录下

self.strategy.initialize(model_provider=default_actor_model_provider) initialize 直接传函数,这是什么用法

这是一种依赖注入(Dependency Injection)的设计模式,具体来说是通过函数参数传递来实现的。让我详细解释这种用法:

设计原理

1. 策略模式(Strategy Pattern)

python 复制代码
class Strategy:
    def initialize(self, model_provider):
        # model_provider 是一个函数,负责创建模型实例
        self.model = model_provider()
        
    def execute(self):
        return self.model.inference()

2. 工厂函数(Factory Functions)

python 复制代码
def default_diffusion_module_provider():
    """扩散模型工厂函数"""
    model = load_diffusion_model()
    model.configure(...)
    return model

def default_actor_model_provider():
    """Actor模型工厂函数"""
    model = load_llm_model()
    model.setup(...)
    return model

这种设计的优势

1. 解耦

python 复制代码
# 策略类不需要知道具体如何创建模型
class Strategy:
    def initialize(self, model_provider):
        # 只关心接口,不关心实现
        self.model = model_provider()  # 调用工厂函数

2. 灵活性

python 复制代码
# 可以轻松切换不同的模型提供器
if condition == "diffusion":
    strategy.initialize(diffusion_provider)
elif condition == "llm":
    strategy.initialize(llm_provider)
else:
    strategy.initialize(custom_provider)  # 自定义提供器

3. 可测试性

python 复制代码
# 测试时可以使用mock提供器
def mock_model_provider():
    return MockModel()

strategy.initialize(mock_model_provider)

实际应用示例

python 复制代码
# 定义不同的模型提供器
def cpu_model_provider():
    model = load_model()
    model.to("cpu")
    return model

def gpu_model_provider():
    model = load_model()
    model.to("cuda")
    return model

def quantized_model_provider():
    model = load_model()
    model.quantize()
    return model

# 根据配置选择不同的提供器
config = get_config()
if config.device == "cpu":
    strategy.initialize(cpu_model_provider)
elif config.quantize:
    strategy.initialize(quantized_model_provider)
else:
    strategy.initialize(gpu_model_provider)

在 SGLang 中的具体实现

从你提供的代码片段来看,SGLang 可能这样实现:

python 复制代码
def default_diffusion_module_provider():
    """提供扩散模型实例"""
    from sglang.models.diffusion import DiffusionModel
    model = DiffusionModel(
        model_path=config.model_path,
        device=config.device
    )
    model.load_weights()
    return model

def default_actor_model_provider():
    """提供LLM Actor模型实例"""
    from sglang.models.llm import LLMActor
    model = LLMActor(
        model_path=config.model_path,
        tokenizer_path=config.tokenizer_path
    )
    model.setup_inference()
    return model

# 策略类使用
class InferenceStrategy:
    def initialize(self, model_provider):
        # 延迟初始化,只在需要时创建模型
        self._model_provider = model_provider
        self._model = None
    
    @property
    def model(self):
        if self._model is None:
            self._model = self._model_provider()
        return self._model

为什么这样设计?

  1. 延迟加载: 模型只在真正需要时才创建
  2. 配置分离: 模型创建逻辑与使用逻辑分离
  3. 扩展性: 添加新模型类型只需新增提供器函数
  4. 资源管理: 可以更好地控制模型加载时机和资源使用

这种设计在深度学习框架中很常见,特别是在需要支持多种模型架构或硬件配置的场景中。

依赖注入(Dependency Injection)和策略模式(Strategy Pattern)是两种不同的设计模式,它们在目的、应用场景和实现方式上都有区别:

核心区别

方面 依赖注入(DI) 策略模式
主要目的 解耦组件创建与使用 封装可互换的算法
关注点 对象依赖关系的管理 行为的选择和替换
粒度 架构级模式 算法级模式
关系方向 单向:容器→组件 双向:上下文↔策略

详细分析

1. 依赖注入(Dependency Injection)

核心思想:将依赖对象的创建和注入从使用对象中分离出来。

python 复制代码
# 传统方式 - 紧耦合
class Service:
    def __init__(self):
        self.database = MySQLDatabase()  # 直接创建依赖

# 依赖注入方式 - 松耦合
class Service:
    def __init__(self, database):  # 依赖通过参数注入
        self.database = database

# 使用
db = MySQLDatabase()
service = Service(db)  # 依赖从外部注入

DI 容器示例

python 复制代码
class DIContainer:
    def __init__(self):
        self._services = {}
    
    def register(self, name, provider):
        self._services[name] = provider
    
    def get(self, name):
        return self._services[name]()

# 配置依赖
container = DIContainer()
container.register('database', lambda: MySQLDatabase())
container.register('logger', lambda: FileLogger())

class Service:
    def __init__(self):
        self.db = container.get('database')
        self.logger = container.get('logger')

2. 策略模式(Strategy Pattern)

核心思想:定义一系列算法,使其可以相互替换。

python 复制代码
from abc import ABC, abstractmethod

# 策略接口
class PaymentStrategy(ABC):
    @abstractmethod
    def pay(self, amount):
        pass

# 具体策略
class CreditCardPayment(PaymentStrategy):
    def pay(self, amount):
        print(f"Credit card payment: ${amount}")

class PayPalPayment(PaymentStrategy):
    def pay(self, amount):
        print(f"PayPal payment: ${amount}")

# 上下文
class ShoppingCart:
    def __init__(self, payment_strategy: PaymentStrategy):
        self._payment_strategy = payment_strategy
    
    def checkout(self, amount):
        self._payment_strategy.pay(amount)

# 使用
cart = ShoppingCart(CreditCardPayment())
cart.checkout(100)  # 使用信用卡支付

cart = ShoppingCart(PayPalPayment())
cart.checkout(200)  # 使用PayPal支付

关键区别点

1. 关注点不同

  • DI:关注"谁创建对象"和"如何传递依赖"
  • 策略模式:关注"使用哪个算法"和"如何切换算法"

2. 应用层次不同

python 复制代码
# 依赖注入 - 解决对象创建问题
class UserService:
    def __init__(self, user_repo, email_service, logger):
        # 所有依赖都是注入的
        self.user_repo = user_repo
        self.email_service = email_service
        self.logger = logger

# 策略模式 - 解决算法选择问题
class DataProcessor:
    def __init__(self, sort_strategy, filter_strategy):
        # 策略模式关注行为的选择
        self.sort_strategy = sort_strategy
        self.filter_strategy = filter_strategy
    
    def process(self, data):
        data = self.filter_strategy.filter(data)
        return self.sort_strategy.sort(data)

3. 可以结合使用

实际上,两者经常结合使用:

python 复制代码
# 策略接口
class CompressionStrategy(ABC):
    @abstractmethod
    def compress(self, data):
        pass

# 具体策略
class ZipCompression(CompressionStrategy):
    def compress(self, data):
        return f"ZIP compressed: {data}"

class GzipCompression(CompressionStrategy):
    def compress(self, data):
        return f"GZIP compressed: {data}"

# 使用依赖注入配置策略
class FileProcessor:
    def __init__(self, compression_strategy: CompressionStrategy):  # DI
        self.compression = compression_strategy  # 策略模式
    
    def process_file(self, data):
        return self.compression.compress(data)

# 配置
container.register(
    'compression', 
    lambda: ZipCompression()  # 可以轻松切换为 GzipCompression
)

processor = FileProcessor(container.get('compression'))

总结

特性 依赖注入 策略模式
主要目标 控制反转,解耦依赖 封装算法,支持替换
解决的问题 "如何获得依赖对象" "使用哪个算法"
典型应用 服务定位、组件管理 排序、压缩、支付等算法
关系性质 创建关系 行为关系
变化频率 依赖关系相对稳定 算法可能频繁切换

简单记忆

  • 依赖注入:解决"对象从哪里来"的问题
  • 策略模式:解决"用什么方法做"的问题

在实际项目中,两者经常协同工作:使用依赖注入来管理策略对象的创建和生命周期。

相关推荐
手把手入门14 小时前
23种设计模式
设计模式
qqxhb14 小时前
系统架构设计师备考第59天——SOA原则&设计模式
设计模式·系统架构·版本管理·标准化·松耦合·可复用·服务粒度
Yeniden14 小时前
【设计模式】桥接模式大白话讲解
设计模式·桥接模式
崎岖Qiu14 小时前
【设计模式笔记10】:简单工厂模式示例
java·笔记·设计模式·简单工厂模式
数据知道1 天前
Go语言设计模式:工厂模式详解
开发语言·设计模式·golang·go语言·工厂模式
懒羊羊不懒@1 天前
JavaSe—泛型
java·开发语言·人工智能·windows·设计模式·1024程序员节
rookie_fly1 天前
基于Vue的数字输入框指令
前端·vue.js·设计模式
Yeniden1 天前
【设计模式】# 外观模式(Facade)大白话讲解!
java·设计模式·外观模式
Yeniden1 天前
【设计模式】 组合模式(Composite)大白话讲解
java·设计模式·组合模式