| 原则 | 核心含义 | PHP 实践要点 |
|---|---|---|
| S 单一职责 (SRP) | 一个类只做一件事,只有一个引起变化的原因 | 拆分 God Class,Service/Repository/Entity 分层,Trait 复用横切逻辑 |
| O 开闭原则 (OCP) | 对扩展开放,对修改关闭 | 接口/抽象类定义契约,策略模式/装饰器模式注入新行为,避免修改核心类 |
| L 里氏替换 (LSP) | 子类必须能替换父类而不破坏程序正确性 | 严格遵守父类契约,不强化前置条件、不弱化后置条件,慎用继承优先组合 |
| I 接口隔离 (ISP) | 依赖精准接口,不依赖不需要的方法 | 拆分大接口为多个小接口(如 LoggerInterface、CacheableInterface),类实现所需接口 |
| D 依赖倒置 (DIP) | 高层模块不依赖低层实现,均依赖抽象 | 构造函数注入接口,使用 Symfony/Illuminate 容器自动装配,避免 new 具体类 |
<?php
class ShopProduct {
public $title = 'default';
public $price = 0;
}
$p = new ShopProduct();
$p->title = "My Book"; // 无拼写检查
$p->price = -99; // 无业务校验
$p->publicher = "Unknown"; // 动态属性,拼写错误不报错
弊端:拼写错误静默失败、无校验逻辑、无法延迟加载、破坏封装、重构极难。
<?php
class ShopProduct
{
private string $title = 'default';
private float $price = 0.0;
public function getTitle(): string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = trim($title); // 自动清理
return $this; // 链式调用
}
public function getPrice(): float
{
return $this->price;
}
public function setPrice(float $price): self
{
if ($price < 0) {
throw new \InvalidArgumentException('Price cannot be negative');
}
$this->price = $price;
return $this;
}
// 只读属性:仅 Getter
public function getFormattedPrice(): string
{
return '¥' . number_format($this->price, 2);
}
}
// 使用
$p = new ShopProduct();
$p->setTitle(" Clean Code ")->setPrice(59.9);
echo $p->getTitle(); // "Clean Code"
echo $p->getFormattedPrice(); // "¥59.90"
<?php
class ImmutableProduct
{
public function __construct(
public readonly string $title,
public readonly float $price,
public readonly \DateTimeImmutable $publishedAt
) {}
// 无需 Getter/Setter,外部不可修改,内部也不可修改
public function withPrice(float $newPrice): self
{
return new self($this->title, $newPrice, $this->publishedAt); // 返回新实例
}
}
$p = new ImmutableProduct("Domain-Driven Design", 79.0, new \DateTimeImmutable());
$p2 = $p->withPrice(69.0); // 价格变更创建新对象,原对象不变
<?php
// 定义契约
interface PaymentGatewayInterface
{
public function charge(float $amount, string $currency): TransactionResult;
}
// 具体实现
class StripeGateway implements PaymentGatewayInterface { /* ... */ }
class AlipayGateway implements PaymentGatewayInterface { /* ... */ }
// 高层服务依赖抽象
class OrderService
{
public function __construct(
private PaymentGatewayInterface $gateway,
private LoggerInterface $logger
) {}
public function pay(Order $order): void
{
$result = $this->gateway->charge($order->total(), 'CNY');
$this->logger->info('Payment processed', ['order_id' => $order->id()]);
}
}
// 容器配置(Symfony/Illuminate 自动装配无需显式配置)
// services.yaml
// services:
// App\Service\OrderService:
// arguments:
// $gateway: '@App\Payment\StripeGateway' // 或通过环境变量切换
<?php
// 差:硬编码
class EmailSender {
public function send() { mail('admin@example.com', ...); }
}
// 好:配置注入
class EmailSender {
public function __construct(
private string $fromAddress,
private string $adminAddress,
private string $smtpHost,
private int $smtpPort
) {}
// 从 .env / config.yaml 注入
}
<?php
// 控制器/服务中
public function export(ExporterInterface $exporter): string
{
return $exporter->export($this->data);
}
// 运行时可切换:CsvExporter、ExcelExporter、PdfExporter
// 测试时注入 MockExporter 验证交互,无需真实 IO
readonly、DateTimeImmutable、Value Object 减少副作用,天然线程安全。「好的架构不是预先设计出来的,而是在不断重构中演化出来的。」—— 从今天开始,每次修改代码前问自己:这是否违反了 SOLID?