本文目录导读:

- 策略模式(Strategy Pattern)
- 策略接口 + 闭包/回调
- 命令模式(Command Pattern)
- 表驱动方法(Table-Driven)
- 基于注解/属性(PHP 8+)
- 简单实用场景 - 提前返回
- 选择建议
在 PHP 中抽象分支有多种方式,我从简单到复杂给你介绍几种常用方法:
策略模式(Strategy Pattern)
这是最经典的分支抽象方式:
<?php
// 定义策略接口
interface PaymentStrategy {
public function pay(float $amount): string;
}
// 具体策略实现
class AlipayStrategy implements PaymentStrategy {
public function pay(float $amount): string {
return "使用支付宝支付:{$amount}元";
}
}
class WechatPayStrategy implements PaymentStrategy {
public function pay(float $amount): string {
return "使用微信支付:{$amount}元";
}
}
class BankCardStrategy implements PaymentStrategy {
public function pay(float $amount): string {
return "使用银行卡支付:{$amount}元";
}
}
// 上下文类
class PaymentContext {
private $strategy;
public function __construct(PaymentStrategy $strategy) {
$this->strategy = $strategy;
}
public function setStrategy(PaymentStrategy $strategy) {
$this->strategy = $strategy;
}
public function executePayment(float $amount): string {
return $this->strategy->pay($amount);
}
}
// 工厂类(可选)
class PaymentFactory {
public static function create(string $type): PaymentStrategy {
return match($type) {
'alipay' => new AlipayStrategy(),
'wechat' => new WechatPayStrategy(),
'bank' => new BankCardStrategy(),
default => throw new \InvalidArgumentException("未知支付方式: {$type}")
};
}
}
// 使用示例
$payment = new PaymentContext(PaymentFactory::create($_POST['method']));
echo $payment->executePayment(100);
策略接口 + 闭包/回调
PHP 的函数式特性让分支抽象更简洁:
<?php
class PriceCalculator {
private $rules = [];
// 注册价格计算规则
public function addRule(string $type, callable $calculator): void {
$this->rules[$type] = $calculator;
}
public function calculate(string $type, float $price): float {
if (!isset($this->rules[$type])) {
throw new \LogicException("未定义的规则类型: {$type}");
}
return ($this->rules[$type])($price);
}
}
// 使用示例
$calculator = new PriceCalculator();
$calculator->addRule('normal', function($price) {
return $price;
});
$calculator->addRule('discount', function($price) {
return $price * 0.8; // 8折
});
$calculator->addRule('vip', function($price) {
return $price * 0.6; // 6折
});
// 动态添加规则
$calculator->addRule('seasonal', function($price) {
return $price * 0.7 - 50; // 7折并减50
});
echo $calculator->calculate('vip', 100); // 输出 60
命令模式(Command Pattern)
用于需要解耦调用者和执行者的场景:
<?php
interface Command {
public function execute(): mixed;
}
class UserCreateCommand implements Command {
public function __construct(private array $data) {}
public function execute(): mixed {
// 创建用户的业务逻辑
return "创建用户: " . $this->data['name'];
}
}
class UserUpdateCommand implements Command {
public function __construct(private int $id, private array $data) {}
public function execute(): mixed {
// 更新用户的业务逻辑
return "更新用户 #{$this->id}";
}
}
class UserDeleteCommand implements Command {
public function __construct(private int $id) {}
public function execute(): mixed {
// 删除用户的业务逻辑
return "删除用户 #{$this->id}";
}
}
// 命令执行器
class CommandInvoker {
public function run(Command $command): mixed {
return $command->execute();
}
}
// 命令工厂
class CommandFactory {
public static function make(string $action, array $params): Command {
return match($action) {
'create' => new UserCreateCommand($params),
'update' => new UserUpdateCommand($params['id'], $params['data']),
'delete' => new UserDeleteCommand($params['id']),
default => throw new \InvalidArgumentException("未知操作")
};
}
}
$invoker = new CommandInvoker();
$command = CommandFactory::make('create', ['name' => '张三']);
$result = $invoker->run($command);
表驱动方法(Table-Driven)
适用于规则明确且可能比较多的情况:
<?php
class RouteHandler {
private $routes = [];
public function register(array $routes): void {
$this->routes = array_merge($this->routes, $routes);
}
public function handle(string $route, array $params): mixed {
if (!isset($this->routes[$route])) {
throw new \LogicException("路由不存在: {$route}");
}
$handler = $this->routes[$route];
// 处理不同的处理器类型
if (is_callable($handler)) {
return $handler($params);
}
if (is_string($handler) && str_contains($handler, '@')) {
[$class, $method] = explode('@', $handler);
$instance = new $class();
return $instance->$method($params);
}
if (is_array($handler)) {
[$class, $method] = $handler;
$instance = new $class();
return $instance->$method($params);
}
throw new \InvalidArgumentException("非法路由处理方式");
}
}
// 路由表
$routes = [
'user.create' => 'UserController@create',
'user.update' => 'UserController@update',
'user.delete' => function($params) {
return "闭包处理删除逻辑: " . json_encode($params);
},
];
$router = new RouteHandler();
$router->register($routes);
// 动态处理
$result = $router->handle('user.create', ['name' => '李四']);
基于注解/属性(PHP 8+)
现代 PHP 支持属性,可以实现更优雅的抽象:
<?php
#[Attribute(Attribute::TARGET_METHOD)]
class Route {
public function __construct(public string $path) {}
}
#[Attribute(Attribute::TARGET_CLASS)]
class Controller {
public function __construct(public string $name) {}
}
#[Controller(name: 'user')]
class UserController {
#[Route('/user/list')]
public function list(): array {
return ['users' => []];
}
#[Route('/user/create')]
public function create(array $data): array {
return ['created' => true, 'data' => $data];
}
}
// 简单的属性路由器
class AttributeRouter {
public function dispatch(string $path): mixed {
$controllers = get_classes_with_attribute(Controller::class);
foreach ($controllers as $class) {
$reflection = new \ReflectionClass($class);
$methods = $reflection->getMethods();
foreach ($methods as $method) {
$attributes = $method->getAttributes(Route::class);
foreach ($attributes as $attribute) {
$route = $attribute->newInstance();
if ($route->path === $path) {
$instance = $class;
return $instance->{$method->getName()}($_POST);
}
}
}
}
throw new \RuntimeException("路由未找到: {$path}");
}
}
简单实用场景 - 提前返回
有时候最简单的方式反而最清晰:
<?php
function processOrder(Order $order): string {
// 逐步验证和提前返回
if ($order->isCancelled()) {
return '订单已取消';
}
if (!$order->hasStock()) {
return '库存不足';
}
if (!$order->hasValidCoupon()) {
return '优惠券无效';
}
// 主流程
$order->pay();
$order->ship();
return '订单处理成功';
}
选择建议
| 方法 | 适用场景 |
|---|---|
| 策略模式 | 算法/业务逻辑可选,需要扩展性 |
| 闭包/回调 | 动态规则,规则简单不复杂 |
| 命令模式 | 操作可回滚、需要队列、需要日志 |
| 表驱动 | 大量固定映射关系,路由分发 |
| 注意 | 永远优先考虑最简单的方案 |
实际项目中,建议结合使用,比如策略模式负责业务逻辑抽象,表驱动和闭包负责轻量处理,命令模式负责复杂操作。
过度设计也是一种反模式,合适的才最好。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播