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

如何使用SOLID/整洁代码/设计模式重构含switch分支的PHP函数?

重构方案

核心优化点

  • 消除switch分支:将饮品类型与对应价格、提示文案抽为统一配置映射,符合开闭原则,后续新增饮品类目无需修改原有校验逻辑,仅需新增配置项即可
  • 拆分校验逻辑:每个校验方法仅负责单一规则校验,符合单一职责原则,代码可读性和可维护性大幅提升
  • 消除硬编码:所有阈值、提示文案均抽为可配置项,后续调整规则无需修改业务逻辑

重构后代码

// 先在类中定义统一配置常量,也可以根据需求放到配置文件中
protected const DRINK_PRICE_MAP = [
    'tea' => 0.4,
    'coffee' => 0.5,
    'chocolate' => 0.6,
];
protected const MIN_SUGARS = 0;
protected const MAX_SUGARS = 2;

protected function execute(InputInterface $input, OutputInterface $output): int
{
    $this->setDrinkType($input);
    $drinkType = $this->drinkType;

    // 校验饮品类型合法性
    if (!isset(self::DRINK_PRICE_MAP[$drinkType])) {
        $output->writeln('饮品类型仅支持茶、咖啡、巧克力');
        return 0;
    }

    // 校验支付金额是否足够
    $money = $input->getArgument('money');
    $drinkPrice = self::DRINK_PRICE_MAP[$drinkType];
    if ($money < $drinkPrice) {
        $output->writeln(sprintf('%s的售价为%.1f', $this->getDrinkDisplayName($drinkType), $drinkPrice));
        return 0;
    }

    // 校验糖量合法性
    if (!$this->hasCorrectSugars($input)) {
        $output->writeln(sprintf('糖量需在%d到%d之间', self::MIN_SUGARS, self::MAX_SUGARS));
        return 0;
    }

    // 所有校验通过,输出订单信息
    $this->printOrderInfo($input, $output);
    return 0;
}

protected function hasCorrectSugars($input): bool
{
    $sugars = $input->getArgument('sugars');
    return $sugars >= self::MIN_SUGARS && $sugars <= self::MAX_SUGARS;
}

// 把原checkSugars方法重命名为更符合功能的printOrderInfo,职责更清晰
protected function printOrderInfo($input, $output): void
{
    $sugars = $input->getArgument('sugars');
    $output->write('您已订购一杯' . $this->getDrinkDisplayName($this->drinkType));
    $this->isExtraHot($input, $output);
    $output->write(',加' . $sugars . '份糖');
    if ($sugars > 0) {
        $output->write('(附赠搅拌棒)');
    }
    $output->writeln('');
}

// 新增饮品名称映射方法,支持后续多语言或者显示名调整
protected function getDrinkDisplayName(string $drinkType): string
{
    $displayNameMap = [
        'tea' => '茶',
        'coffee' => '咖啡',
        'chocolate' => '巧克力',
    ];
    return $displayNameMap[$drinkType] ?? $drinkType;
}

额外优化说明

  • 原allowedDrinkTypes属性可以直接移除,直接通过DRINK_PRICE_MAP的键判断合法饮品类型,避免两处维护同一份规则的不一致风险
  • 如果后续业务复杂度提升,还可以把每种饮品做成独立的饮品类继承统一的饮品接口,把价格、显示名、自身校验规则都封装到对应类中,进一步解耦,更符合依赖倒置原则
  • 所有返回码也可以抽为常量,比如const RESPONSE_SUCCESS = 0,后续调整返回值无需全局修改

内容的提问来源于stack exchange,提问作者Rafael Pastor García

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 14:54:02