1. 单例模式 (Singleton)
作用:确保一个类只有一个实例,并提供全局访问点。
使用场景:数据库连接、日志记录器、配置管理。
代码示例:
class Database {
private static $instance;
private function __construct() {} // 防止外部实例化
private function __clone() {} // 防止克隆
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function query($sql) { /* ... */ }
}
// 使用
$db1 = Database::getInstance();
$db2 = Database::getInstance();
var_dump($db1 === $db2); // true
注意事项:单例模式可能增加耦合性,需谨慎使用。
2. 工厂模式 (Factory)
作用:封装对象的创建逻辑,客户端无需关心具体实现。
使用场景:支付方式、日志存储方式等需要动态创建对象的场景。
代码示例:
interface Logger {
public function log($message);
}
class FileLogger implements Logger {
public function log($message) {
file_put_contents('app.log', $message, FILE_APPEND);
}
}
class DatabaseLogger implements Logger {
public function log($message) { /* 记录到数据库 */ }
}
class LoggerFactory {
public static function create($type) {
return match ($type) {
'file' => new FileLogger(),
'database' => new DatabaseLogger(),
default => throw new Exception("不支持的日志类型"),
};
}
}
// 使用
$logger = LoggerFactory::create('file');
$logger->log("Error occurred!");
3. 观察者模式 (Observer)
作用:定义对象间的一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都会收到通知。
使用场景:事件处理系统、消息订阅、用户注册后发送邮件和短信。
代码示例:
interface Subject {
public function attach(Observer $observer);
public function detach(Observer $observer);
public function notify();
}
class UserRegistration implements Subject {
private $observers = [];
public function attach(Observer $observer) {
$this->observers[] = $observer;
}
public function notify() {
foreach ($this->observers as $observer) {
$observer->handle();
}
}
public function registerUser() {
// 注册逻辑...
$this->notify(); // 触发通知
}
}
interface Observer {
public function handle();
}
class EmailNotifier implements Observer {
public function handle() { echo "发送欢迎邮件\n"; }
}
class SMSNotifier implements Observer {
public function handle() { echo "发送短信通知\n"; }
}
// 使用
$registration = new UserRegistration();
$registration->attach(new EmailNotifier());
$registration->attach(new SMSNotifier());
$registration->registerUser();
4. 策略模式 (Strategy)
作用:定义一系列算法,使其可以相互替换,算法的变化独立于客户端。
使用场景:支付方式选择、排序算法切换、折扣计算。
代码示例:
interface DiscountStrategy {
public function calculate($price): float;
}
class NoDiscount implements DiscountStrategy {
public function calculate($price): float { return $price; }
}
class BlackFridayDiscount implements DiscountStrategy {
public function calculate($price): float { return $price * 0.7; }
}
class Checkout {
private $discountStrategy;
public function __construct(DiscountStrategy $strategy) {
$this->discountStrategy = $strategy;
}
public function finalizeOrder($price) {
return $this->discountStrategy->calculate($price);
}
}
// 使用
$checkout = new Checkout(new BlackFridayDiscount());
echo $checkout->finalizeOrder(100); // 输出 70
5. 装饰器模式 (Decorator)
作用:动态地为对象添加功能,避免继承导致的类爆炸。
使用场景:为对象动态添加日志、缓存、权限校验等功能。
代码示例:
interface Notifier {
public function send($message);
}
class EmailNotifier implements Notifier {
public function send($message) { echo "发送邮件:$message\n"; }
}
abstract class NotifierDecorator implements Notifier {
protected $notifier;
public function __construct(Notifier $notifier) {
$this->notifier = $notifier;
}
}
class SMSDecorator extends NotifierDecorator {
public function send($message) {
$this->notifier->send($message);
echo "发送短信:$message\n";
}
}
// 使用
$notifier = new EmailNotifier();
$notifier = new SMSDecorator($notifier);
$notifier->send("订单已发货");
// 输出:
// 发送邮件:订单已发货
// 发送短信:订单已发货
6. 适配器模式 (Adapter)
作用:将一个类的接口转换成客户端期望的另一个接口。
使用场景:兼容旧系统、集成第三方库。
代码示例:
// 旧类(需要适配)
class LegacyWeatherService {
public function getTemperatureF() { return 68; } // 返回华氏度
}
// 新接口(客户端期望的接口)
interface WeatherService {
public function getTemperatureC(): float;
}
// 适配器类
class WeatherAdapter implements WeatherService {
private $legacyService;
public function __construct(LegacyWeatherService $service) {
$this->legacyService = $service;
}
public function getTemperatureC(): float {
$f = $this->legacyService->getTemperatureF();
return ($f - 32) * 5 / 9; // 转换为摄氏度
}
}
// 使用
$legacyService = new LegacyWeatherService();
$adapter = new WeatherAdapter($legacyService);
echo $adapter->getTemperatureC(); // 输出 20
7. 依赖注入 (Dependency Injection)
作用:将依赖对象的创建和绑定移到外部,降低耦合。
使用场景:需要松耦合的模块化架构。
代码示例:
interface CacheDriver {
public function get($key);
}
class RedisCache implements CacheDriver {
public function get($key) { /* Redis 实现 */ }
}
class UserService {
private $cache;
public function __construct(CacheDriver $cache) {
$this->cache = $cache;
}
public function getUser($id) {
$user = $this->cache->get("user_$id");
// 逻辑...
}
}
// 使用(依赖由外部容器注入)
$cache = new RedisCache();
$userService = new UserService($cache);
8. 责任链模式 (Chain of Responsibility)
作用:将请求沿着处理链传递,直到有对象处理它。
使用场景:中间件、权限校验链、日志处理管道。
代码示例:
abstract class Handler {
private $nextHandler;
public function setNext(Handler $handler) {
$this->nextHandler = $handler;
}
public function handle($request) {
if ($this->nextHandler !== null) {
return $this->nextHandler->handle($request);
}
return null;
}
}
class AuthHandler extends Handler {
public function handle($request) {
if (!$request['is_authenticated']) {
throw new Exception("未授权");
}
return parent::handle($request);
}
}
class LoggingHandler extends Handler {
public function handle($request) {
echo "记录请求日志\n";
return parent::handle($request);
}
}
// 使用
$auth = new AuthHandler();
$logging = new LoggingHandler();
$auth->setNext($logging);
$auth->handle(['is_authenticated' => true]);
总结
模式 | 核心思想 | 典型场景 |
---|---|---|
单例模式 | 全局唯一实例 | 数据库连接、配置管理 |
工厂模式 | 封装对象创建 | 动态创建不同子类对象 |
观察者模式 | 一对多事件通知 | 用户行为触发多系统响应 |
策略模式 | 算法可替换 | 支付方式、折扣策略 |
装饰器模式 | 动态扩展功能 | 添加日志、缓存等非核心功能 |
适配器模式 | 接口兼容 | 整合旧系统或第三方库 |
责任链模式 | 链式处理请求 | 中间件、权限校验链 |
设计原则:
一、单一职责原则 (Single Responsibility Principle, SRP)
定义:一个类应该仅有一个引起变化的原因。
应用场景:避免将多个功能耦合在同一个类中。
PHP示例:
// 违反SRP的类:同时处理用户数据和日志记录
class User {
public function saveToDatabase() { /*...*/ }
public function logActivity() { /*...*/ }
}
// 改进后拆分职责
class User {
public function saveToDatabase() { /*...*/ }
}
class Logger {
public function logActivity() { /*...*/ }
}
二、开闭原则 (Open/Closed Principle, OCP)
定义:对扩展开放,对修改关闭。
应用场景:通过抽象和继承扩展功能,而非修改原有代码。
PHP示例:
// 抽象支付接口
interface Payment {
public function pay(float $amount);
}
// 扩展新支付方式无需修改已有类
class Alipay implements Payment {
public function pay(float $amount) { /*...*/ }
}
class WechatPay implements Payment {
public function pay(float $amount) { /*...*/ }
}
三、里氏替换原则 (Liskov Substitution Principle, LSP)
定义:子类必须能够完全替换父类且不破坏系统。
应用场景:继承关系中的方法重写需保持行为一致性。
PHP示例:
class Bird {
public function fly(): string {
return "Flying";
}
}
// 错误示例:企鹅不会飞,违反LSP
class Penguin extends Bird {
public function fly(): string {
throw new Exception("Cannot fly");
}
}
// 正确做法:拆分接口(符合接口隔离原则)
interface Flyable {
public function fly();
}
class Sparrow implements Flyable { /*...*/ }
class Penguin { /*...*/ }
四、接口隔离原则 (Interface Segregation Principle, ISP)
定义:客户端不应依赖它不需要的接口。
应用场景:避免庞大臃肿的接口,按需拆分。
PHP示例:
// 违反ISP的接口
interface Worker {
public function code();
public function test();
}
// 拆分后
interface Developer {
public function code();
}
interface Tester {
public function test();
}
五、依赖倒置原则 (Dependency Inversion Principle, DIP)
定义:高层模块不应依赖低层模块,二者都应依赖抽象。
应用场景:通过依赖注入降低耦合度。
PHP示例:
// 低层模块
class MySQLConnection {
public function connect() { /*...*/ }
}
// 高层模块依赖抽象
interface DBConnection {
public function connect();
}
class UserService {
public function __construct(private DBConnection $db) {}
}
// 使用依赖注入
$userService = new UserService(new MySQLConnection());
六、迪米特法则 (Law of Demeter, LoD)
定义:一个对象应对其他对象保持最少了解。
应用场景:减少类间直接依赖,通过中介通信。
PHP示例:
class Order {
private $customer;
// 违反LoD:直接访问Customer的地址
public function getCustomerAddress() {
return $this->customer->getAddress()->getFullAddress();
}
// 改进后:委托给Customer处理
public function getCustomerAddress() {
return $this->customer->getFullAddress();
}
}
原则综合应用建议
原则 | 核心目标 | 典型技术手段 |
---|---|---|
单一职责原则 | 功能解耦 | 类拆分、职责分离 |
开闭原则 | 扩展友好 | 抽象类/接口、策略模式 |
里氏替换原则 | 继承安全 | 接口隔离、契约设计 |
接口隔离原则 | 接口精简 | 接口拆分、角色分离 |
依赖倒置原则 | 降低耦合 | 依赖注入、控制反转容器 |
迪米特法则 | 减少依赖链 | 门面模式、中介者模式 |