设计模式
设计模式分类:
- 创建型:单例模式;工厂模式;抽象工厂模式;建造者模式;
- 结构性:适配器模式;装饰器模式;门面模式;
- 行为型:策略模式;观察者模式;责任链模式;
- 架构型:注册模式

- | 单例模式:确保一个类只有一个实例。(优点:全局只有一个入口点,易维。节省资源。缺点:测试困难)
- l 工厂模式:定义创建对象的接口,由子类决定实例化那个类(优点:单一职责;缺点:类数量膨胀)
- l 抽象工厂模式:提供接口创建一系列相关或者以来的对象,无需指定具体类(优点:产品一致性;缺点:扩展困难)
- l 策略模式:定义算法族,封装并互换,让算法独立于使用它的客户端(优点:避免大量if-else,开闭原则;缺点:类数量多,客户端需要知道策略)
- l 观察者模式:当一个对象状态发生变化时,依赖它的对象会受到通知并自动更新(优点:松耦合;缺点:类数不好确定)
- l 装饰器模式:动态给对象添加功能,不改变原有类,适用于扩展功能(优点:灵活扩展;缺点:多层嵌套)
- | 注册模式:解决全局共享和交换对象,将对象注册到全局数组,需要时直接获取(优点:集中管理,动态扩展;缺点:全局扩展,测试困难)
- l 适配器模式:兼容不同接口,让不能兼容的类一起调用(优点:兼容性好;缺点:增加复杂度)
- l 建造者模式:分布构建复杂对象,避免构造函数参数过多(优点:链式调用,参数校验;缺点:代码冗余)
- | 责任链模式:请求传递,解耦发送者和接收者。(优点:解耦发送者和接收者,灵活职责分配;缺点:调试困难,性能损耗)
设计模式详情&场景样例:
一. 单例模式:
确保一个类只有一个实例,常用于全局资源管理
好处:
节省资源:避免重复连接数据库;统一管理:所有数据库操作通过同一入口;易于维护:修改连接配置只需改一处;性能优化:减少 TCP 握手和认证开销
1.数据库连接场景:
<?php
class Database {
private static $instance = null;
private $connection;
// 私有化构造方法,防止外部 new
private function __construct() {
try {
$this->connection = new PDO(
"mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8mb4",
DB_USER,
DB_PASS,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_PERSISTENT => false // 是否持久连接
]
);
} catch (PDOException $e) {
die("数据库连接失败: " . $e->getMessage());
}
}
// 私有化克隆方法,防止克隆
private function __clone() {}
// 私有化反序列化方法,防止反序列化
private function __wakeup() {}
// 获取单例实例
public static function getInstance(): self {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
// 获取数据库连接
public function getConnection(): PDO {
return $this->connection;
}
// 执行查询
public function query($sql, $params = []) {
$stmt = $this->connection->prepare($sql);
$stmt->execute($params);
return $stmt;
}
// 插入数据
public function insert($table, $data) {
$fields = array_keys($data);
$placeholders = ':' . implode(', :', $fields);
$sql = "INSERT INTO {$table} (" . implode(',', $fields) . ") VALUES ({$placeholders})";
$stmt = $this->connection->prepare($sql);
return $stmt->execute($data);
}
}
// ------------------使用示例--------------------
$db = Database::getInstance();
$connection = $db->getConnection();
// 查询
$users = $db->query("SELECT * FROM users WHERE status = ?", [1]);
// 插入
$db->insert('users', [
'name' => '阿陌',
'email' => 'amo@111.com'
]);
?>
2.购物车场景(确保用户购物车全局唯一)
<?php
class Cart {
private static $instance = null;
private $items = [];
// 私有化构造,防止外部 new
private function __construct() {}
private function __clone() {}
public static function getInstance(): self {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function addItem($productId, $quantity) {
$this->items[$productId] = ($this->items[$productId] ?? 0) + $quantity;
}
public function getItems() {
return $this->items;
}
}
//-------------使用样例-----------------
// 使用:无论调用多少次,都是同一个购物车实例
$cart = Cart::getInstance();
$cart->addItem(1001, 2);
$cart2 = Cart::getInstance();
$cart2->addItem(1002, 1);
var_dump($cart === $cart2); // true
?>
二. 工厂模式
封装对象创建逻辑,解耦调用方和具体类。
1.促销场景:
<?php
// 促销接口
interface Promotion {
public function calculate($originalPrice);
public function getDescription();
}
// 满减促销
class FullReductionPromotion implements Promotion {
private $threshold; // 满多少
private $reduction; // 减多少
public function __construct($threshold, $reduction) {
$this->threshold = $threshold;
$this->reduction = $reduction;
}
public function calculate($originalPrice) {
if ($originalPrice >= $this->threshold) {
return $originalPrice - $this->reduction;
}
return $originalPrice;
}
public function getDescription() {
return "满 {$this->threshold} 减 {$this->reduction}";
}
}
// 折扣促销
class DiscountPromotion implements Promotion {
private $discount; // 折扣率,如 0.8 表示 8 折
public function __construct($discount) {
$this->discount = $discount;
}
public function calculate($originalPrice) {
return $originalPrice * $this->discount;
}
public function getDescription() {
return $this->discount * 10 . "折";
}
}
// 第二件半价
class SecondHalfPromotion implements Promotion {
public function calculate($originalPrice) {
// 需要结合数量实现,这里简化
return $originalPrice;
}
public function getDescription() {
return "第二件半价";
}
}
// 促销工厂
class PromotionFactory {
public static function create($type, $config): Promotion {
switch ($type) {
case 'full_reduction':
return new FullReductionPromotion(
$config['threshold'],
$config['reduction']
);
case 'discount':
return new DiscountPromotion($config['discount']);
case 'second_half':
return new SecondHalfPromotion();
default:
throw new Exception("不支持的促销类型: {$type}");
}
}
}
// ----------------使用示例:创建多种促销活动-------------
$promotions = [
PromotionFactory::create('full_reduction', ['threshold' => 200, 'reduction' => 30]),
PromotionFactory::create('discount', ['discount' => 0.85]),
PromotionFactory::create('flash_sale', ['sale_price' => 99, 'limit' => 2]),
];
$price = 300;
foreach ($promotions as $promo) {
echo $promo->getDescription() . " 最终价: " . $promo->calculate($price) . "\n";
}
2. 物流服务场景:
<?php
interface Logistics {
public function createOrder($orderInfo);
public function calculateFee($weight, $destination);
}
class SFLogistics implements Logistics {
public function __construct() {
}
public function createOrder($orderInfo) {
// 顺丰下单 API 调用
return true;
}
public function calculateFee($weight, $destination) {
// 顺丰计价规则:首重 12 元,续重 2 元/kg
$fee = 12 + max(0, $weight - 1) * 2;
// 偏远地区加价
$remoteAreas = ['新疆', '西藏', '内蒙古'];
if (in_array($destination, $remoteAreas)) {
$fee += 10;
}
return $fee;
}
}
class JDLogistics implements Logistics {
public function createOrder($orderInfo) {
// 京东物流 API
return "京东物流单号: JD" . time();
}
public function calculateFee($weight, $destination) {
// 京东物流计价:首重 10 元,续重 1.8 元/kg
return 10 + $weight * 1.8;
}
}
// 物流工厂
class LogisticsFactory {
private static $providers = [
'sf' => SFLogistics::class,
'jd' => JDLogistics::class,
];
public static function create($providerCode): Logistics {
if (!isset(self::$providers[$providerCode])) {
throw new Exception("不支持的物流商: {$providerCode}");
}
$className = self::$providers[$providerCode];
return new $className();
}
// 根据用户地址智能选择最优物流商
public static function getBestProvider($address, $weight): Logistics {
// 智能推荐逻辑
if (strpos($address, '北京') !== false && $weight > 10) {
// 北京地区大件用京东物流
return self::create('jd');
}
//else if 其他物流逻辑
else {
// 默认顺丰(服务好)
return self::create('sf');
}
}
}
//---------- 使用示例-------------
//获取运费
class ShippingService {
public function calculateShippingFee($orderId, $address, $weight) {
// 智能选择物流商
$logistics = LogisticsFactory::getBestProvider($address, $weight);
$fee = $logistics->calculateFee($weight, $address);
// 保存到订单
Order::where('id', $orderId)->update([
'shipping_fee' => $fee,
'logistics_provider' => get_class($logistics)
]);
return $fee;
}
//发货
public function shipOrder($orderId, $providerCode) {
$order = Order::find($orderId);
$logistics = LogisticsFactory::create($providerCode);
$trackingNumber = $logistics->createOrder([
'order_no' => $order->order_no,
'address' => $order->shipping_address,
'weight' => $order->weight
]);
$order->tracking_number = $trackingNumber;
$order->status = 'shipped';
$order->save();
return $trackingNumber;
}
}
3.批量导入导出场景
<?php
interface ImportExport {
public function export($data, $filePath);
}
class CSVHandler implements ImportExport {
public function export($data, $filePath) {
$handle = fopen($filePath, 'w');
// 写入表头
if (!empty($data)) {
fputcsv($handle, array_keys($data[0]));
// 写入数据
foreach ($data as $row) {
fputcsv($handle, $row);
}
}
fclose($handle);
return true;
}
}
class ExcelHandler implements ImportExport {
public function export($data, $filePath) {
$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
// 写入表头
$col = 'A';
foreach (array_keys($data[0]) as $header) {
$sheet->setCellValue($col . '1', $header);
$col++;
}
// 写入数据
$row = 2;
foreach ($data as $item) {
$col = 'A';
foreach ($item as $value) {
$sheet->setCellValue($col . $row, $value);
$col++;
}
$row++;
}
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx');
$writer->save($filePath);
return true;
}
}
// 导出工厂
class ImportExportFactory {
public static function create($format): ImportExport {
switch (strtolower($format)) {
case 'csv':
return new CSVHandler();
case 'xlsx':
case 'xls':
return new ExcelHandler();
default:
throw new Exception("不支持的格式: {$format}");
}
}
}
//------------使用示例:批量导出--------
class ProductImportService {
public function export($productIds, $format) {
$data = [];//导出的数据列表
$handler = ImportExportFactory::create($format);
$filePath = storage_path("exports/products_" . time() . ".{$format}");
$handler->export($data, $filePath);
return $filePath;
}
}
三. 抽象工厂模式
创建一系列相关对象,比工厂模式更宏观。
1.订单导出器场景(多格式+多平台)
// 问题:需要导出不同格式(PDF、Excel)和不同平台(淘宝、京东)
interface OrderExportFactory {
public function createHeader();
public function createBody();
public function createFooter();
}
// 淘宝 Excel 导出
class TaobaoExcelFactory implements OrderExportFactory {
public function createHeader() { return new TaobaoExcelHeader(); }
public function createBody() { return new TaobaoExcelBody(); }
public function createFooter() { return new TaobaoExcelFooter(); }
}
// 京东 PDF 导出
class JingdongPDFFactory implements OrderExportFactory {
public function createHeader() { return new JingdongPDFHeader(); }
public function createBody() { return new JingdongPDFBody(); }
public function createFooter() { return new JingdongPDFFooter(); }
}
// -------------------使用场景--------------------------
function exportOrders(OrderExportFactory $factory) {
$header = $factory->createHeader();
$body = $factory->createBody();
$footer = $factory->createFooter();
return $header->render() . $body->render() . $footer->render();
}
$export = exportOrders(new TaobaoExcelFactory()); // 淘宝 Excel
$export = exportOrders(new JingdongPDFFactory()); // 京东 PDF
四. 策略模式
定义一系列算法,动态切换
商品多维度推荐列表场景:
<?php
// 推荐策略接口
interface RecommendStrategy {
public function recommend($userId, $limit = 10);
}
// 基于浏览历史的推荐
class HistoryBasedRecommend implements RecommendStrategy {
public function recommend($userId, $limit = 10) {
// 获取用户浏览历史
$viewedProducts = ProductView::where('user_id', $userId)
->orderBy('viewed_at', 'desc')
->limit(20)
->pluck('product_id');
// 找到同分类的商品
$categories = Product::whereIn('id', $viewedProducts)
->pluck('category_id');
$recommendations = Product::whereIn('category_id', $categories)
->whereNotIn('id', $viewedProducts)
->inRandomOrder()
->limit($limit)
->get();
return $recommendations;
}
}
// 热门商品推荐
class HotProductsRecommend implements RecommendStrategy {
public function recommend($userId, $limit = 10) {
return Product::where('status', 1)
->orderBy('sale_count', 'desc')
->limit($limit)
->get();
}
}
// 新品推荐
class NewArrivalRecommend implements RecommendStrategy {
public function recommend($userId, $limit = 10) {
return Product::where('status', 1)
->orderBy('created_at', 'desc')
->limit($limit)
->get();
}
}
// 个性化推荐(组合多种策略)
class PersonalizedRecommend implements RecommendStrategy {
private $strategies = [];
public function __construct() {
$this->strategies = [
new HistoryBasedRecommend(),
new HotProductsRecommend()
];
}
public function recommend($userId, $limit = 10) {
$allRecommendations = collect();
foreach ($this->strategies as $strategy) {
$recs = $strategy->recommend($userId, $limit);
$allRecommendations = $allRecommendations->merge($recs);
}
// 去重并排序
return $allRecommendations->unique('id')
->take($limit);
}
}
// 推荐上下文
class RecommendEngine {
private $strategy;
public function setStrategy(RecommendStrategy $strategy) {
$this->strategy = $strategy;
return $this;
}
public function getRecommendations($userId, $limit = 10) {
$startTime = microtime(true);
$results = $this->strategy->recommend($userId, $limit);
$duration = microtime(true) - $startTime;
// 记录推荐日志
Log::info("推荐策略执行", [
'strategy' => get_class($this->strategy),
'user_id' => $userId,
'count' => $results->count(),
'duration' => $duration
]);
return $results;
}
}
// ---------------使用示例---------------------
class HomeController {
public function index(Request $request) {
$userId = auth()->id();
$recommendEngine = new RecommendEngine();
// 根据场景选择策略
if ($request->get('tab') === 'hot') {
$recommendEngine->setStrategy(new HotProductsRecommend());
} elseif ($request->get('tab') === 'new') {
$recommendEngine->setStrategy(new NewArrivalRecommend());
} elseif (Cache::has("user_profile:{$userId}")) {
// 有用户画像,使用个性化推荐
$recommendEngine->setStrategy(new PersonalizedRecommend());
} else {
// 新用户,使用浏览历史推荐
$recommendEngine->setStrategy(new HistoryBasedRecommend());
}
$products = $recommendEngine->getRecommendations($userId, 20);
return view('goods', ['products' => $products]);
}
}
五. 观察者模式
事件驱动,一对多依赖。
订单状态通知场景:
interface Observer {
public function update($event, $data);
}
// 短信通知
class SMSNotifier implements Observer {
public function update($event, $data) {
if ($event == 'order.paid') {
echo "发送短信给用户 {$data['user_id']}: 订单支付成功\n";
}
}
}
// 邮件通知
class EmailNotifier implements Observer {
public function update($event, $data) {
if ($event == 'order.shipped') {
echo "发送邮件给用户 {$data['user_id']}: 订单已发货\n";
}
}
}
// 库存更新
class InventoryUpdater implements Observer {
public function update($event, $data) {
if ($event == 'order.cancelled') {
echo "恢复库存: 商品 {$data['product_id']} 数量 {$data['quantity']}\n";
}
}
}
class Order {
private $observers = [];
public function attach(Observer $observer) {
$this->observers[] = $observer;
}
public function notify($event, $data) {
foreach ($this->observers as $observer) {
$observer->update($event, $data);
}
}
public function pay($userId, $orderId) {
// 支付逻辑
$this->notify('order.paid', [
'user_id' => $userId,
'order_id' => $orderId,
'points' => 100,
]);
}
}
// ---------------使用方式------------
$order = new Order();
$order->attach(new SMSNotifier());
$order->attach(new EmailNotifier());
$order->attach(new InventoryUpdater());
$order->pay(10086, 'ORDER123');
// 输出:
// 发送短信给用户 10086: 订单支付成功
六. 责任链模式:
多个对象处理同一个请求,避免if-else堆积
商品审核场景:
<?php
// 审核处理器抽象类
abstract class ReviewHandler {
protected $next;
protected $level;
public function setNext(ReviewHandler $handler) {
$this->next = $handler;
return $handler;
}
public function handle($product) {
if ($this->canHandle($product)) {
$result = $this->process($product);
if ($result === false) {
return false;
}
}
if ($this->next) {
return $this->next->handle($product);
}
return true;
}
abstract protected function canHandle($product);
abstract protected function process($product);
}
// 商品信息审核(自动审核)
class InfoReviewHandler extends ReviewHandler {
protected $level = 1;
protected function canHandle($product) {
return true; // 所有商品都需要基础信息审核
}
protected function process($product) {
$errors = [];
// 检查商品名称
if (strlen($product->name) < 2 || strlen($product->name) > 100) {
$errors[] = "商品名称长度必须在2-100之间";
}
// 检查价格
if ($product->price <= 0 || $product->price > 100000) {
$errors[] = "商品价格必须在0-100000之间";
}
// 检查库存
if ($product->stock < 0) {
$errors[] = "库存不能为负数";
}
// 检查描述
if (empty($product->description)) {
$errors[] = "商品描述不能为空";
}
if (!empty($errors)) {
$product->review_status = 'failed';
$product->review_reason = implode('; ', $errors);
$product->save();
return false;
}
return true;
}
}
// 图片审核(机审+人审)
class ImageReviewHandler extends ReviewHandler {
protected $level = 2;
protected function canHandle($product) {
return !empty($product->images);
}
protected function process($product) {
// 调用图片审核API
$apiResult = ImageModeration::check($product->images);
if ($apiResult['has_illegal']) {
$product->review_status = 'failed';
$product->review_reason = "商品图片包含违规内容: {$apiResult['reason']}";
$product->save();
return false;
}
// 疑似违规进入人工审核
if ($apiResult['is_suspicious']) {
$product->review_status = 'manual';
$product->review_reason = "图片疑似违规,需人工审核";
$product->save();
return false;
}
return true;
}
}
// 价格审核(价格异常需人工审核)
class PriceReviewHandler extends ReviewHandler {
protected $level = 4;
protected function canHandle($product) {
// 价格低于成本价50%或高于市场价200%
$costPrice = $product->cost_price;
$marketPrice = $this->getMarketPrice($product->category_id);
return $product->price < $costPrice * 0.5 || $product->price > $marketPrice * 2;
}
protected function process($product) {
$product->review_status = 'manual';
$product->review_reason = "价格异常,需人工审核";
$product->save();
// 发送通知给运营人员
Notification::send('运营组', "商品 {$product->name} 价格异常");
return false;
}
private function getMarketPrice($categoryId) {
// 获取该类目的平均市场价
return Product::where('category_id', $categoryId)
->avg('price') ?? 100;
}
}
// -----------使用示例:商品审核服务--------
class ProductReviewService {
public function review($productId) {
$product = Product::find($productId);
// 构建责任链
$infoHandler = new InfoReviewHandler();
$imageHandler = new ImageReviewHandler();
$priceHandler = new PriceReviewHandler();
$infoHandler->setNext($imageHandler)
->setNext($priceHandler);
$result = $infoHandler->handle($product);
if ($result && $product->review_status !== 'manual') {
$product->review_status = 'approved';
$product->reviewed_at = now();
$product->save();
// 上架商品
$product->status = 'on';
$product->save();
}
return $product->review_status;
}
}
七. 适配器模式
兼容不同接口,让不兼容的类能一起工作。
多仓库商品同步场景:
内容都是商品名|价格|数量|主图,但是每个供应商仓库对应的传参格式/传参名/传参内容
// 问题:仓库1,仓库2,仓库3,API 不同,需要统一接口
interface ProductSync {
public function sync($product);
}
// 仓库1适配器
class WareHouseAdapter1 implements ProductSync {
private $warehouseAPI;
public function __construct() {
$this->warehouseAPI = new WareHouseAPI();
}
public function sync($product) {
// 转换数据格式
$data = [
'title' => $product->name,
'price' => $product->price,
'stock' => $product->quantity,
'pic' => $product->pic_link,
];
return $this->warehouseAPI->uploadProduct($data);
}
}
// 仓库2适配器
class WareHouseAdapter2 implements ProductSync {
private $wHAPI;
public function __construct() {
$this->wHAPI = new WhAPI();
}
public function sync($product) {
// 仓库2API传参格式不同,方法名也不同
$data = [
'sku_name' => $product->name,
'sale_price' => $product->price,
'quantity' => $product->quantity,
];
return $this->wHAPI->createGood($data);
}
}
// --------------使用:统一调用--------------------
function syncToAllPlatforms($product) {
$adapters = [
new WareHouseAdapter1(),
new WareHouseAdapter2(),
];
foreach ($adapters as $adapter) {
$adapter->sync($product);
}
}
八. 建造者模式:
分步构建复杂对象,避免构造函数参数过多。
1.构建XX表(商品表)搜索条件场景:
// 问题:商品搜索有几十个参数,构造函数难以维护
class ProductSearchBuilder {
private $params = [];
//关键词搜索
public function setKeyword($keyword) {
$this->params['keyword'] = $keyword;
return $this;
}
//……其他维度搜索按业务需求补充……
//价格区间搜索
public function setPriceRange($min, $max) {
$this->params['price_min'] = $min;
$this->params['price_max'] = $max;
return $this;
}
//排序
public function setSort($field, $order = 'asc') {
$this->params['sort'] = $field;
$this->params['order'] = $order;
return $this;
}
//分页
public function setPage($page, $size = 20) {
$this->params['page'] = $page;
$this->params['size'] = $size;
return $this;
}
public function build() {
return new ProductSearchQuery($this->params);
}
}
// ----使用方式:清晰直观----
$searchQuery = (new ProductSearchBuilder())
->setKeyword('手机')
//->setCategory(100)->setPriceRange(1000, 5000)
->setSort('price', 'desc')
->setPage(1, 20)
->build();


浙公网安备 33010602011771号