
本文介绍通过查找表、策略模式等 oop 手段消除硬编码 if/else 和 switch,提升代码可维护性与扩展性,适用于产品类型差异化展示等典型场景。
本文介绍通过查找表、策略模式等 oop 手段消除硬编码 if/else 和 switch,提升代码可维护性与扩展性,适用于产品类型差异化展示等典型场景。
在实际开发中,频繁使用 if-elseif-else 或 switch 判断产品类型(如 "DVD"、"Book"、"Furniture")并执行不同逻辑,不仅导致代码臃肿、难以测试,更违背开闭原则——新增产品类型需修改原有分支逻辑。幸运的是,借助面向对象设计思想与数据驱动方法,我们能优雅地解耦类型与行为。
✅ 推荐方案一:配置驱动的查找表(轻量高效)
最直接的替代方式是将“类型 → 展示字段 + 单位”映射关系外置为关联数组,实现零条件判断:
<?php $displayConfig = [
'DVD' => ['field' => 'size', 'unit' => 'MB'],
'Furniture'=> ['field' => 'dimensions', 'unit' => ''],
'Book' => ['field' => 'weight', 'unit' => 'Kg'],
];
// 安全获取配置(避免未定义类型导致 Notice)
if (!isset($displayConfig[$product['product_type']])) {
throw new InvalidArgumentException("Unknown product type: {$product['product_type']}");
}
$config = $displayConfig[$product['product_type']];
echo "<p>" . ucfirst($config['field']) . ": " . $product[$config['field']] . $config['unit'] . "</p>";
?>
⚠️ 注意事项:
- 建议配合 isset() 或 array_key_exists() 校验键存在性,防止运行时错误;
- 可将 $displayConfig 提取为常量、配置文件或服务类属性,便于统一管理和单元测试;
- 若字段名/单位逻辑复杂(如需格式化、多字段拼接),此方案可升级为策略对象。
✅ 推荐方案二:策略模式(高内聚、易扩展)
当每类产品行为差异较大(不止字段展示,还涉及计算、验证、持久化等),应封装为独立策略类:
interface ProductDisplayStrategy {
public function render(array $product): string;
}
class DvdDisplayStrategy implements ProductDisplayStrategy {
public function render(array $product): string {
return "<p>Size: {$product['size']}MB</p>";
}
}
class BookDisplayStrategy implements ProductDisplayStrategy {
public function render(array $product): string {
return "<p>Weight: {$product['weight']}Kg</p>";
}
}
class FurnitureDisplayStrategy implements ProductDisplayStrategy {
public function render(array $product): string {
return "<p>Dimensions: {$product['dimensions']}</p>";
}
}
// 策略工厂(解耦创建逻辑)
class ProductStrategyFactory {
private static $strategies = [
'DVD' => DvdDisplayStrategy::class,
'Book' => BookDisplayStrategy::class,
'Furniture'=> FurnitureDisplayStrategy::class,
];
public static function get(string $type): ProductDisplayStrategy {
if (!isset(self::$strategies[$type])) {
throw new InvalidArgumentException("No strategy registered for type: $type");
}
return new self::$strategies[$type]();
}
}
// 使用方式(无任何条件语句)
$strategy = ProductStrategyFactory::get($product['product_type']);
echo $strategy->render($product);
该模式天然支持:
- 新增产品类型只需新增策略类 + 注册到工厂,无需修改现有代码;
- 每个策略可独立单元测试、依赖注入、复用;
- 未来可结合依赖注入容器(如 PHP-DI)自动解析策略。
✅ 总结:何时选择哪种方式?
| 场景 | 推荐方案 | 优势 |
|---|---|---|
| 展示逻辑简单(字段+单位) | 查找表(Array Map) | 开发快、内存占用低、易理解 |
| 行为复杂、需复用或测试 | 策略模式 + 工厂 | 高内聚、松耦合、符合 SOLID 原则 |
| 类型动态加载(如插件系统) | 策略模式 + 自动发现机制 | 支持运行时扩展 |
最终目标不是“消灭所有 if”,而是将变化点隔离、显式化、可配置化。拒绝条件语句的深层意义,在于推动代码向声明式、可组合、易演化的方向演进。











