国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

PHPer月工作總結之觀察者&裝飾器模式

MadPecker / 928人閱讀

摘要:我們可以把取消發貨單和取消訂單看成一個被觀察或被訂閱的類實例的對象,一旦發生取消行為,我們立即通知各個觀察者做出相對應的行為。裝飾器模式裝飾器思想,不管以前業務邏輯,甚至不去讀,調用之前的接口裝飾上新的數據,達到自己的目的。

前言

還是每月的目標至少寫一篇文章,一晃八月份就要過去了,這個月依然沒有什么產出,毫無疑問最近的狀態就是不停的工作,不停的加班。所以還是把最近工作進行一個總結,首先來我看看這段時間我做了什么?

工作內容

這次工作的主要內容就是“取消發貨單”功能,這個功能的上下文是這樣的:我們支付成功的訂單會在一段時間后被拆成發貨單,本次開發任務的目的就是通過客戶端對用戶開放申請取消發貨單的功能。其實這個功能就是發貨單服務生成退款單之后回調訂單服務的一系列undo操作,其次這些邏輯我們目前都是同步調用未異步隊列化,接著我們來梳理下大致有哪些undo操作:

undo訂單&訂單商品信息->undo商品庫存->undo各種促銷優惠活動的庫存->undo錢包余額->log->消息

顯而易見這些操作基本和取消訂單的邏輯絕大多數一致,加之取消訂單的代碼已經很老了,而且可維護性,擴展性,可用性都很差,所以我又多了一項任務“重構取消訂單”。我們接著來梳理下取消訂單的邏輯:

undo訂單&訂單商品信息->undo商品庫存->undo各種促銷優惠活動的庫存->生成退款單->undo錢包余額->undo贈品->undo紅包->log->消息

下圖清晰的梳理了兩者操作的內容:

建模

通過上面我們對業務邏輯的梳理,其實這兩個功能絕大多數的邏輯是可以公用的,且這每個子邏輯都可以獨立成為一個個體,這么看來這就是典型的訂閱通知模型“觀察者模式”應用的場景。我們可以把“取消發貨單”和“取消訂單”看成一個被觀察或被訂閱的類實例的對象,一旦發生取消行為,我們立即通知各個觀察者做出相對應的行為。本來php是提供了觀察者的接口SplSuject和SplObserver,我們只需實現該接口即可,但是SplSuject的attach成員方法不支持閉包(使用閉包可以使觀察者被通知的時候再實例化,節省了一定的性能和內存空間),所以我自己最后重新實現了該接口。最后我們的模型如下:

填充業務邏輯

完成上面的建模,其實我們的功能其實就算完成一半了,剩下的事情就是在每個類文件填充對應獨立的業務邏輯即可。

/**
 * 被觀察者接口
 *
 * 由于php原生的被觀察者接口SplSubject不支持注冊閉包,即自己實現一下這個接口
 */
Interface ObservableInterface
{
    /**
     * 注冊觀察者對象
     *
     * @param  Closure $closure 閉包形式注冊
     * @return void
     */
    public function attach(Closure $closure);

    /**
     * 剔除觀察者對象
     *
     * @param  ObserverInterface $observer 觀察者對象
     * @return void
     */
    public function detach(ObservableInterface $observer);

    /**
     * 通知觀察者對象
     *
     * @return void
     */
    public function notify();
}

/**
 * 觀察者接口
 *
 * php原生觀察者接口SplObserver
 */
Interface ObserverInterface
{
    /**
     * 觀察者操作
     *
     * @param  ObservableInterface $observable 被觀察者對象
     * @return void
     */
    public function operate(ObservableInterface $observable);
}
/**
 * 取消訂單被訂閱實體
 *
 * 被訂閱/被觀察者實體
 */
class Observable implements ObservableInterface
{
    /**
     * 注冊的觀察者/訂閱對象
     *
     * @var array
     */
    private $observers = [];

    /**
     * 已經被通知的觀察者/訂閱對象
     *
     * @var array
     */
    private $hadNotify = [];


    /**
     * 構造函數
     *
     * @return void
     */
    public function __construct(params...)
    {
        
    }

    /**
     * 注冊觀察者/訂閱對象
     *
     * @param  Closure $closure 閉包形式注冊
     * @return void
     */
    public function attach(Closure $closure)
    {
        $this->observers[] = $closure;
    }

    /**
     * 批量注冊觀察者/訂閱對象
     *
     * @param  array $closures 閉包形式注冊
     * @return void
     */
    public function multiAttach($closures = [])
    {
        $closures = array_filter($closures, function ($var) {
            if ($var instanceof Closure) {
                return $var;
            }
        });
        $this->observers = array_merge($this->observers, $closures);
    }

    /**
     * 剔除觀察者/訂閱對象
     *
     * @param  ObserverInterface $observer 觀察者對象/訂閱對象
     * @return void
     */
    public function detach(ObservableInterface $observer)
    {
        foreach ($this->observers as $k => $v) {
            if ($v() === $observer) {
                unset($this->observers[$k]);
            }
        }
    }

    /**
     * 通知觀察者/訂閱對象
     *
     * @return void
     */
    public function notify()
    {
        foreach ($this->observers as $v) {
            $instance = $v();
            if (in_array($instance, $this->hadNotify, true)) {
                // 不通知重復的訂閱
                continue;
            }
            $instance->operate($this);
            $this->hadNotify[] = $instance;
        }
    }
}

最后我們在我們的控制器類中完成調用如下:

class OrderController
{
    /**
     * 取消訂單
     */
    public function cancel()
    {
        try {
            /* 創建取消訂單的被觀察者 */
            $subject = new Observable();

            // 注冊訂單觀察者
            $subject->attach(function () {
                return new Order();
            });

            // 注冊商品觀察者
            $subject->attach(function () {
                return new Goods();
            });

            // 注冊促銷商品觀察者
            $subject->attach(function () {
                return new PromotionGoods();
            });

            // 注冊退款單觀察者
            $subject->attach(function () {
                return new RefundOrder();
            });

            // 注冊錢包觀察者
            $subject->attach(function () {
                return new Wallet();
            });

            // 注冊紅包觀察者
            $subject->attach(function () {
                return new Bonus();
            });

            // 注冊贈品觀察者
            $subject->attach(function () {
                return new Gift();
            });

            // 注冊日志觀察者
            $subject->attach(function () {
                return new Log();
            });

            // 注冊消息觀察者
            $subject->attach(function () {
                return new Notice();
            });

            /* 廣播 */
            $subject->notify();
        } catch (Exception $e) {
            # code...
        }
    }
}

class DeliveryController
{
    /**
     * 取消發貨單
     */
    public function cancel()
    {
        try {
            /* 創建取消發貨單的被觀察者 */
            $subject = new Observable();

            // 注冊訂單觀察者
            $subject->attach(function () {
                return new Order();
            });

            // 注冊商品觀察者
            $subject->attach(function () {
                return new Goods();
            });

            等等(不注冊紅包和贈品觀察者)...

            /* 廣播 */
            $subject->notify();
        } catch (Exception $e) {
            # code...
        }
    }
}

這樣的話我們完全高內聚松耦合了我們的業務代碼,如果未來需要增加新的邏輯,我們只需要注冊新的觀察者即可。這樣重構完成代碼后,我們未來在取消訂單的時候只需要注冊訂單的觀察者到取消訂單的被觀察者即可,其他的觀察者我們再注冊到一個異步執行的取消訂單的被觀察者實例中,通過這樣我們就能給用戶帶來好的體驗,用戶取消訂單的操作我們只需通知訂單狀態變更,其余的觀察者我們異步通知保證最終成功,在未來實現這個功能時我們的業務代碼根本不需要動,只需要改變調用方式。

裝飾器模式

裝飾器思想,不管以前業務邏輯,甚至不去讀,調用之前的接口裝飾上新的數據,達到自己的目的。最近遇到的問題,在我們的訂單列表加一些字段,但是訂單列表的代碼基本無法閱讀和調整,最后想到了裝飾器的思想,最后我們完全不需要管之前的邏輯,我們只需調用現有的類方法,再裝飾上我們想要的數據即可,這樣就最簡化和快捷的達到了我們的目的。

Easy PHP:一個極速輕量級的PHP全??蚣?/pre>

掃面下方二維碼關注我的技術公眾號,及時為大家推送我的原創技術分享

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/25693.html

相關文章

  • 這兩年多我寫PHP業務代碼的方式是如何進化的

    摘要:曾今誰都有過迷茫期,下面是我開始開發中,不斷改變的代碼組織方式。 曾今 誰都有過迷茫期,下面是我開始PHP開發中,不斷改變的代碼組織方式。 初期:所有代碼一股腦控制器controller 曾今只是簡單的理解MVC 中期:業務代碼抽象一部分到模型層model 開始覺得model層是否該做點什么了 后期:業務代碼控制器,模型層只寫db的curd方法 復雜的業務代碼使contro...

    qqlcbb 評論0 收藏0
  • PHPer工作總結構建抽獎工具

    摘要:這個月的計劃本來是對基礎的數據結構做一個沉淀,但是,但是,但是這個月的的狀態就是工作工作既然這樣就總結下這個月的工作吧。 前言 目標是每個月寫一篇文章,對從事編程開發的基礎知識做一個學習總結。這個月的計劃本來是對基礎的數據結構做一個沉淀,但是,但是,但是......這個月的的狀態就是工作工作...既然這樣就總結下這個月的工作吧。 工作內容 促銷活動的抽獎工具,具備如下功能: 根據不同...

    W_BinaryTree 評論0 收藏0
  • php設計模式

    摘要:我們今天也來做一個萬能遙控器設計模式適配器模式將一個類的接口轉換成客戶希望的另外一個接口。今天要介紹的仍然是創建型設計模式的一種建造者模式。設計模式的理論知識固然重要,但 計算機程序的思維邏輯 (54) - 剖析 Collections - 設計模式 上節我們提到,類 Collections 中大概有兩類功能,第一類是對容器接口對象進行操作,第二類是返回一個容器接口對象,上節我們介紹了...

    Dionysus_go 評論0 收藏0
  • php設計模式

    摘要:我們今天也來做一個萬能遙控器設計模式適配器模式將一個類的接口轉換成客戶希望的另外一個接口。今天要介紹的仍然是創建型設計模式的一種建造者模式。設計模式的理論知識固然重要,但 計算機程序的思維邏輯 (54) - 剖析 Collections - 設計模式 上節我們提到,類 Collections 中大概有兩類功能,第一類是對容器接口對象進行操作,第二類是返回一個容器接口對象,上節我們介紹了...

    vspiders 評論0 收藏0
  • 設計模式總結

    摘要:,命令模式,將行為請求者和行為實現者解耦,將行為抽象為對象。解釋器模式,迭代器模式,將集合對象的存儲數據和遍歷數據職責分離。即將遍歷的責任交給迭代器返回的迭代器,迭代器。 設計模式總結 創建型:除了直接new來實例化對象外,提供了多種隱藏創建邏輯的生成對象的方法 結構型:通過對象和類的組合,得到新的結構和功能 行為型:解決對象之間的通行和功能職責分配 詳細分類 工廠 簡單工廠...

    quietin 評論0 收藏0

發表評論

0條評論

MadPecker

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<