首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

關鍵詞匹配項目實戰 Day 13:從 if-else 地獄到策略模式重構的覺醒之路

     編輯:PHP 相關知識

故事背景

小帥帥完成了關鍵詞匹配的初版邏輯:根據淘寶商品標題/屬性中的「男裝/女裝/情侶裝/童裝」關鍵字,動態構建核心詞與黑名單,再拼接 SQL 查詢。代碼雖能跑通,卻被架構師于老大一頓批評:

  1. 硬編碼 if-else 鏈,擴展新品類需改動核心邏輯(違反開閉原則)
  2. 業務規則與數據訪問耦合,難以單元測試

于老大的重構示範:策略模式 + 工廠方法

<?php
// 1. 領域模型:封裝淘寶 API 返回數據
class SelectorItem {
    private $item;
    public function __construct($item) { $this->item = $item; }
    public function __get($name) { return $this->item->$name ?? null; }

    public static function createFromApi($num_iid): self {
        $client = new TopClient(); // 省略配置
        $req = new ItemGetRequest();
        $req->setFields('props_name,property_alias,detail_url,cid,title');
        $req->setNumIid($num_iid);
        $resp = $client->execute($req);
        if (isset($resp->code)) throw new Exception($resp->msg, $resp->code);
        return new self($resp->item);
    }
}

// 2. 關鍵字容器
class CharList {
    private $core = [], $blacklist = [];
    public function addCore($c) { if (!in_array($c, $this->core)) $this->core[] = $c; }
    public function addBlacklist($c) { if (!in_array($c, $this->blacklist)) $this->blacklist[] = $c; }
    public function getCore() { return $this->core; }
    public function getBlacklist() { return $this->blacklist; }
}

// 3. 策略接口
abstract class CharListHandle {
    protected $charlist;
    public function __construct(CharList $cl) { $this->charlist = $cl; }
    abstract public function exec();
}

// 4. 具體策略
class MenCharListHandle extends CharListHandle {
    public function exec() {
        $this->charlist->addCore('男裝');
        $this->charlist->addBlacklist('女');
    }
}
class WomenCharListHandle extends CharListHandle { /* ... */ }
class LoversCharListHandle extends CharListHandle { /* ... */ }
class ChildrenCharListHandle extends CharListHandle { /* ... */ }

// 5. 選擇器:策略註冊表 + 工廠方法
class Selector {
    private static $map = [
        '男裝'     => MenCharListHandle::class,
        '女裝'     => WomenCharListHandle::class,
        '情侶裝'   => LoversCharListHandle::class,
        '童裝'     => ChildrenCharListHandle::class,
    ];

    public static function select($num_iid) {
        $item = SelectorItem::createFromApi($num_iid);
        $matchTitle = $item->title . $item->props_name;
        $charlist = new CharList();

        foreach (self::$map as $keyword => $handlerClass) {
            if (preg_match("/$keyword/", $matchTitle)) {
                $handler = self::createHandler($handlerClass, $charlist);
                $handler->exec();
            }
        }
        // 後續:用 $charlist->getCore()/getBlacklist() 構建查詢...
    }

    private static function createHandler(string $class, CharList $cl): CharListHandle {
        if (class_exists($class)) return new $class($cl);
        throw new Exception("Handler $class not found");
    }
}

設計模式落地心得

  • 策略模式:將「如何根據品類生成核心/黑名單」封裝為可互換的策略類,新增品類只需新增類、註冊到 $map,零修改核心流程。
  • 工廠方法:createHandler 統一實例化邏輯,支援異常處理與擴展(如依賴注入容器)。
  • 魔術方法 __get:讓 $item->title 透明代理到底層數組,調用端無感知。
  • 單一職責:API 調用、領域模型、業務規則、數據訪問徹底解耦。

優秀程序員的標準

「優秀的程序員寫出可讀、可維護、可擴展的代碼;普通程序員只是寫出能跑通的代碼。」

小帥帥雖然最初不服,但通過這次重構見識到設計模式在實際業務中的威力,決定系統學習《設計模式》並嘗試在後續需求中主動應用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved