PHP 怎么抽象分支

wen PHP项目 1

本文目录导读:

PHP 怎么抽象分支

  1. 策略模式(Strategy Pattern)
  2. 策略接口 + 闭包/回调
  3. 命令模式(Command Pattern)
  4. 表驱动方法(Table-Driven)
  5. 基于注解/属性(PHP 8+)
  6. 简单实用场景 - 提前返回
  7. 选择建议

在 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 '订单处理成功';
}

选择建议

方法 适用场景
策略模式 算法/业务逻辑可选,需要扩展性
闭包/回调 动态规则,规则简单不复杂
命令模式 操作可回滚、需要队列、需要日志
表驱动 大量固定映射关系,路由分发
注意 永远优先考虑最简单的方案

实际项目中,建议结合使用,比如策略模式负责业务逻辑抽象,表驱动和闭包负责轻量处理,命令模式负责复杂操作。

过度设计也是一种反模式,合适的才最好。

抱歉,评论功能暂时关闭!