You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何重构兼顾Strategy与Repository模式的OrderProductFactory?

OrderProductFactory重构优化方案

问题分析

原OrderProductFactory存在两个核心问题:

  • 违反单一职责原则(SRP):同时负责OrderProduct、支付策略、仓储实例三类对象的创建逻辑,职责混杂,后续新增支付方式或仓储类型时,会持续膨胀代码量,提升维护成本。
  • 魔术数组$repositoryParams不合理:依赖松散的数组传递参数,缺乏类型约束,可读性差且易出现参数名拼写错误、缺失等运行时问题。

优化方案

1. 拆分工厂,遵循单一职责

将支付策略和仓储的创建逻辑拆分到独立工厂类中,让每个工厂仅负责一类对象的创建,原OrderProductFactory仅专注于组合依赖生成OrderProduct。

拆分后的支付策略工厂

final readonly class OrderPaymentStrategyFactory
{
    public static function create(string $type): OrderProductPaymentStrategy
    {
        return match ($type) {
            CardPayment::name() => new OrderCardPayment(),
            // 新增支付策略时,仅需扩展此处匹配分支
            default => throw new InvalidArgumentException('不支持的支付策略类型: ' . $type),
        };
    }
}

拆分后的仓储工厂(解决魔术数组问题)

用强类型方法替代魔术数组,每个仓储类型对应明确的创建方法,参数类型和数量清晰可查:

final readonly class OrderRepositoryFactory
{
    // Sqlite仓储的强类型创建方法
    public static function createSqlite(string $databasePath): SqliteOrderRepository
    {
        if (empty($databasePath)) {
            throw new InvalidArgumentException('SqliteOrderRepository的数据库路径无效');
        }
        return new SqliteOrderRepository($databasePath);
    }

    // 新增其他仓储类型时,添加对应强类型方法,比如:
    // public static function createMysql(string $host, string $dbName, string $username, string $password): MysqlOrderRepository
    // {
    //     // ...逻辑实现
    // }

    // 可选:保留统一入口方法,基于类型分发到具体创建逻辑
    public static function create(string $type, mixed ...$args): OrderRepository
    {
        return match ($type) {
            SqliteOrderRepository::name() => self::createSqlite(...$args),
            // MysqlOrderRepository::name() => self::createMysql(...$args),
            default => throw new InvalidArgumentException('不支持的仓储类型: ' . $type),
        };
    }
}

简化后的OrderProductFactory

final readonly class OrderProductFactory
{
    // 直接接收已实例化的依赖,职责仅为组合生成OrderProduct
    public static function create(
        OrderProductPaymentStrategy $paymentStrategy,
        OrderRepository $repository
    ): OrderProduct {
        return OrderProduct::for($paymentStrategy, $repository);
    }

    // 可选:保留基于类型字符串的快捷创建入口,内部调用拆分后的工厂
    public static function createFromTypes(
        string $paymentStrategyType,
        string $repositoryType,
        mixed ...$repositoryArgs
    ): OrderProduct {
        $paymentStrategy = OrderPaymentStrategyFactory::create($paymentStrategyType);
        $repository = OrderRepositoryFactory::create($repositoryType, ...$repositoryArgs);
        return self::create($paymentStrategy, $repository);
    }
}

2. 使用Builder模式优化创建流程

如果后续OrderProduct的依赖项增多(比如新增折扣策略、物流配置等),Builder模式会比工厂模式更灵活——它允许逐步构建对象,通过链式调用明确每个配置项,完全避免参数混乱问题。

OrderProductBuilder实现

class OrderProductBuilder
{
    private ?OrderProductPaymentStrategy $paymentStrategy = null;
    private ?OrderRepository $repository = null;

    // 每种支付策略对应明确的配置方法
    public function withCardPayment(): self
    {
        $this->paymentStrategy = new OrderCardPayment();
        return $this;
    }

    // 新增支付策略时,添加对应配置方法
    // public function withAlipayPayment(): self
    // {
    //     $this->paymentStrategy = new OrderAlipayPayment();
    //     return $this;
    // }

    // 每种仓储对应明确的配置方法
    public function withSqliteRepository(string $databasePath): self
    {
        $this->repository = OrderRepositoryFactory::createSqlite($databasePath);
        return $this;
    }

    // 新增仓储类型时,添加对应配置方法
    // public function withMysqlRepository(string $host, string $dbName, string $username, string $password): self
    // {
    //     $this->repository = OrderRepositoryFactory::createMysql($host, $dbName, $username, $password);
    //     return $this;
    // }

    // 构建前校验依赖是否齐全
    public function build(): OrderProduct
    {
        if ($this->paymentStrategy === null || $this->repository === null) {
            throw new LogicException('构建OrderProduct前必须设置支付策略和仓储');
        }
        return OrderProduct::for($this->paymentStrategy, $this->repository);
    }
}

使用Builder创建实例

$orderProduct = (new OrderProductBuilder())
    ->withCardPayment()
    ->withSqliteRepository('/path/to/order.db')
    ->build();

优化后优势

  • 职责清晰:每个工厂/Builder仅负责单一逻辑,后续扩展支付方式或仓储类型时,仅需修改对应类,不影响其他代码。
  • 类型安全:强类型参数替代魔术数组,参数错误在编译阶段即可发现,减少运行时异常。
  • 扩展性强:新增依赖项时,Builder模式无需修改原有方法,只需添加新的配置方法,符合开闭原则。

内容的提问来源于stack exchange,提问作者Vortex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 16:44:56