目錄
Gof類圖及解釋
實例
首頁 後端開發 php教程 淺談PHP中的裝飾器模式

淺談PHP中的裝飾器模式

Jun 23, 2021 pm 06:40 PM
php 裝飾器模式

裝飾器模式允許為一個現有的物件添加新的功能,同時又不改變其結構。本篇文章帶大家了解PHP中的裝飾器模式,介紹一下裝飾器的好處以及最適合的場景。

淺談PHP中的裝飾器模式

工廠模式告一段落,我們來研究其他一些模式。不知道各位大佬有沒有嘗試女裝?據說女裝大佬程式設計師很多喲。其實,今天的裝飾模式就跟化妝這件事很像。相信如果有程式媛MM在的話,馬上就能跟你講清楚這個設計模式。

Gof類圖及解釋

裝飾這兩個字,我們暫且把他變成化妝。首先你得有一張臉,然後打底,然後上妝,可以早上來個淡妝上班,也可以下班的時候補成濃妝出去嗨。當然,碼農們下班的時間點正好是能趕上夜場的下半場的。話說回來,不管怎麼化妝,你的臉還是你的臉,有可能可以化成別人不認識的另一個人,但這的的確確還是你的臉。這就是裝飾器,對物件(臉)進行各種裝飾(化妝),讓這個臉更好看(增加職責)。

GoF定義:動態地為一個物件增加一些額外的職責,就增加功能來說,Decorator模式相比產生子類別更為靈活

GoF類別圖:

淺談PHP中的裝飾器模式

程式碼實作:

interface Component{
    public function operation();
}

class ConcreteComponent implements Component{
    public function operation(){
        echo "I'm face!" . PHP_EOL;
    }
}
登入後複製

很簡單的一個介面和一個實現,這裡我們就把具體的實作類看作是一張臉吧!

abstract class Decorator implements Component{
    protected $component;
    public function __construct(Component $component){
        $this->component = $component;
    }
}
登入後複製

抽象的裝飾者類,實作Component接口,但不實作operation()方法,讓子類別去實作。這裡主要保存一個Componet的引用,一會兒就要對他進行裝飾。對應到上方的具體類,我們就是要準備給臉化妝啦!

class ConcreteDecoratorA extends Decorator{
    public $addedState = 1; // 没什么实际意义的属性,只是区别于ConcreteDecoratorB

    public function operation(){
        echo $this->component->operation() . "Push " . $this->addedState . " cream!" . PHP_EOL;
    }
}
class ConcreteDecoratorB extends Decorator{
    public function operation(){
        $this->component->operation();
        $this->addedBehavior();
    }

    // 没什么实际意义的方法,只是区别于ConcreteDecoratorA
    public function addedBehavior(){
        echo "Push 2 cream!" . PHP_EOL;
    }
}
登入後複製

兩個具體裝飾者。這裡我是塗了兩次霜,畢竟是純爺們,對化妝這事兒真的是不了解。好像第一步應該先是打粉底吧?不過這次就這樣,我們這兩個裝飾器實現的就是在臉上塗兩層霜。

  • 從程式碼可以看出,我們是一直對具體的那個ConcreteComponent物件來進行包裝
  • 再往下的話其實我們是對他的operation()這個方法包裝了兩次,每次都是在前一次的基礎上加了一點點東西
  • 不要糾結於A和B裝飾器上的added屬性和方法,他們只是GoF類圖中用以區別這兩個裝飾器不是同一個東西,每個裝飾器都可以做很多別的事,Component對像也不一定只有operation()這一個方法,我們可以選擇性的去裝飾對像中的全部或者部分方法
  • 好像我們都繼承了Component,直接子類別一路重寫不就行了,搞這費勁幹嘛?親,了解下組合的概念喲,我們的Decorator父類裡面是一個真實對象的引用哦,解耦了自身哦,我們只給真實的對象去做包裝,您可別直接實例化裝飾器來直接用
  • 還是沒懂?好處呢?老系統的類啊、方法啊你敢隨便亂改?想給前任寫的牛(S)逼(B)程式碼擴充新功能時不妨試試裝飾器這貨,說不定有奇效!

手機這玩意乾不過某米、某O、某為,這沒法玩呀,好吧,哥們去專心做手機殼吧!嗯,我先準備了一個透明殼(Component),看起來有點醜,沒辦法,誰叫哥們窮。給某米的加上各種純色(DecoratorA1),然後背後印上各種顏色的植物(DecoratorB1)吧;某O的手機最近喜歡找流量明顯做代言,那我給他的手機殼就用各種炫彩色(DecoratorA2)與明星的卡通頭像(DecoratorB2);最後的某為,好像手機已經開始引領業界潮流了,折疊螢幕這玩意不是要砸我這賣手機殼的生意嘛! !好吧,哥哥不給你們做了,還是跟我的某米、某O混去吧! !

完整程式碼:裝飾模式

https://github.com/zhangyue0503/designpatterns-php/blob/master/04.decorator/source/decorator. php

實例

繼續來發短信,之前我們用工廠模式解決了多個簡訊運營商的問題。這回我們要解決的是簡訊內容模板的問題。對於推廣類的簡訊來說,根據最新的廣告法,我們是不能出現「全國第一」、「全世界第一」這類的詞語的,當然,一些不太文明的用語我們也是不能使用的。

现在的情况是这样的,我们有一个很早之前的短信模板类,里面的内容是固定的,老系统依然还是使用这个模板,老系统是面对的内部员工,对语言内容的要求不高。而新系统则需要向全网发送,也就是内外部的用户都要发送。这时,我们可以用装饰器模式来对老系统的短信模板进行包装。其实说简单点,我们就是用装饰器来做文本替换的功能。好处呢?当然是可以不去改动原来的模板类中的方法就实现了对老模板内容的修改扩展等。

短信发送类图:

淺談PHP中的裝飾器模式

完整源码:短信发送装饰器方法

https://github.com/zhangyue0503/designpatterns-php/blob/master/04.decorator/source/message-decorator.php

<?php
// 短信模板接口
interface MessageTemplate
{
    public function message();
}

// 假设有很多模板实现了上面的短信模板接口
// 下面这个是其中一个优惠券发送的模板实现
class CouponMessageTemplate implements MessageTemplate
{
    public function message()
    {
        return &#39;优惠券信息:我们是全国第一的牛X产品哦,送您十张优惠券!&#39;;
    }
}

// 我们来准备好装饰上面那个过时的短信模板
abstract class DecoratorMessageTemplate implements MessageTemplate
{
    public $template;
    public function __construct($template)
    {
        $this->template = $template;
    }
}

// 过滤新广告法中不允许出现的词汇
class AdFilterDecoratorMessage extends DecoratorMessageTemplate
{
    public function message()
    {
        return str_replace(&#39;全国第一&#39;, &#39;全国第二&#39;, $this->template->message());
    }
}

// 使用我们的大数据部门同事自动生成的新词库来过滤敏感词汇,这块过滤不是强制要过滤的内容,可选择使用
class SensitiveFilterDecoratorMessage extends DecoratorMessageTemplate
{
    public $bigDataFilterWords = [&#39;牛X&#39;];
    public $bigDataReplaceWords = [&#39;好用&#39;];
    public function message()
    {
        return str_replace($this->bigDataFilterWords, $this->bigDataReplaceWords, $this->template->message());
    }
}

// 客户端,发送接口,需要使用模板来进行短信发送
class Message
{
    public $msgType = &#39;old&#39;;
    public function send(MessageTemplate $mt)
    {
        // 发送出去咯
        if ($this->msgType == &#39;old&#39;) {
            echo &#39;面向内网用户发送&#39; . $mt->message() . PHP_EOL;
        } else if ($this->msgType == &#39;new&#39;) {
            echo &#39;面向全网用户发送&#39; . $mt->message() . PHP_EOL;
        }

    }
}

$template = new CouponMessageTemplate();
$message = new Message();

// 老系统,用不着过滤,只有内部用户才看得到
$message->send($template);

// 新系统,面向全网发布的,需要过滤一下内容哦
$message->msgType = &#39;new&#39;;
$template = new AdFilterDecoratorMessage($template);
$template = new SensitiveFilterDecoratorMessage($template);

// 过滤完了,发送吧
$message->send($template);
登入後複製

说明

  • 装饰器的最大好处:一是不改变原有代码的情况下对原有代码中的内容进行扩展,开放封闭原则;二是每个装饰器完成自己的功能,单一职责;三是用组合实现了继承的感觉;
  • 最适用于:给老系统进行扩展
  • 要小心:过多的装饰者会把你搞晕的
  • 不一定都是对同一个方法进行装饰,其实装饰者应该更多的用于对对象的装饰,对对象进行扩展,这里我们都是针对一个方法的输出进行装饰,但仅限此文,装饰器的应用其实更加广泛
  • 装饰器的特点是全部都继承自一个主接口或类,这样的好处就是返回的对象是相同的抽象数据,具有相同的行为属性,否则,就不是装饰之前的对象,而是一个新对象了
  • 有点不好理解没关系,我们这次的例子其实也很勉强,这个设计模式在《Head First设计模式》中有提到Java的I/O系列接口是使用的这种设计模式:FileInputStream、LineNumberInputStream、BufferInputStream等
  • Laravel框架中的中间件管道,这里其实是多种模式的综合应用,其中也应用到了装饰器模式:Laravel HTTP——Pipeline 中间件装饰者模式源码分析
  • 另外在Laravel中,日志处理这里也是对Monolog进行了装饰,有兴趣的同学可以去了解下

推荐学习:《PHP视频教程

以上是淺談PHP中的裝飾器模式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1663
14
CakePHP 教程
1419
52
Laravel 教程
1313
25
PHP教程
1264
29
C# 教程
1237
24
您如何在PHP中解析和處理HTML/XML? 您如何在PHP中解析和處理HTML/XML? Feb 07, 2025 am 11:57 AM

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

在PHP API中說明JSON Web令牌(JWT)及其用例。 在PHP API中說明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

解釋PHP中的晚期靜態綁定(靜態::)。 解釋PHP中的晚期靜態綁定(靜態::)。 Apr 03, 2025 am 12:04 AM

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

php程序在字符串中計數元音 php程序在字符串中計數元音 Feb 07, 2025 pm 12:12 PM

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? 什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? Apr 03, 2025 am 12:03 AM

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。

PHP和Python:比較兩種流行的編程語言 PHP和Python:比較兩種流行的編程語言 Apr 14, 2025 am 12:13 AM

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

PHP行動:現實世界中的示例和應用程序 PHP行動:現實世界中的示例和應用程序 Apr 14, 2025 am 12:19 AM

PHP在電子商務、內容管理系統和API開發中廣泛應用。 1)電子商務:用於購物車功能和支付處理。 2)內容管理系統:用於動態內容生成和用戶管理。 3)API開發:用於RESTfulAPI開發和API安全性。通過性能優化和最佳實踐,PHP應用的效率和可維護性得以提升。

PHP:網絡開發的關鍵語言 PHP:網絡開發的關鍵語言 Apr 13, 2025 am 12:08 AM

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

See all articles