裝飾器模式允許為一個現有的物件添加新的功能,同時又不改變其結構。本篇文章帶大家了解PHP中的裝飾器模式,介紹一下裝飾器的好處以及最適合的場景。
工廠模式告一段落,我們來研究其他一些模式。不知道各位大佬有沒有嘗試女裝?據說女裝大佬程式設計師很多喲。其實,今天的裝飾模式就跟化妝這件事很像。相信如果有程式媛MM在的話,馬上就能跟你講清楚這個設計模式。
Gof類圖及解釋
裝飾這兩個字,我們暫且把他變成化妝。首先你得有一張臉,然後打底,然後上妝,可以早上來個淡妝上班,也可以下班的時候補成濃妝出去嗨。當然,碼農們下班的時間點正好是能趕上夜場的下半場的。話說回來,不管怎麼化妝,你的臉還是你的臉,有可能可以化成別人不認識的另一個人,但這的的確確還是你的臉。這就是裝飾器,對物件(臉)進行各種裝飾(化妝),讓這個臉更好看(增加職責)。
GoF定義:動態地為一個物件增加一些額外的職責,就增加功能來說,Decorator模式相比產生子類別更為靈活
GoF類別圖:
程式碼實作:
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
實例
繼續來發短信,之前我們用工廠模式解決了多個簡訊運營商的問題。這回我們要解決的是簡訊內容模板的問題。對於推廣類的簡訊來說,根據最新的廣告法,我們是不能出現「全國第一」、「全世界第一」這類的詞語的,當然,一些不太文明的用語我們也是不能使用的。
现在的情况是这样的,我们有一个很早之前的短信模板类,里面的内容是固定的,老系统依然还是使用这个模板,老系统是面对的内部员工,对语言内容的要求不高。而新系统则需要向全网发送,也就是内外部的用户都要发送。这时,我们可以用装饰器模式来对老系统的短信模板进行包装。其实说简单点,我们就是用装饰器来做文本替换的功能。好处呢?当然是可以不去改动原来的模板类中的方法就实现了对老模板内容的修改扩展等。
短信发送类图:
完整源码:短信发送装饰器方法
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 '优惠券信息:我们是全国第一的牛X产品哦,送您十张优惠券!'; } } // 我们来准备好装饰上面那个过时的短信模板 abstract class DecoratorMessageTemplate implements MessageTemplate { public $template; public function __construct($template) { $this->template = $template; } } // 过滤新广告法中不允许出现的词汇 class AdFilterDecoratorMessage extends DecoratorMessageTemplate { public function message() { return str_replace('全国第一', '全国第二', $this->template->message()); } } // 使用我们的大数据部门同事自动生成的新词库来过滤敏感词汇,这块过滤不是强制要过滤的内容,可选择使用 class SensitiveFilterDecoratorMessage extends DecoratorMessageTemplate { public $bigDataFilterWords = ['牛X']; public $bigDataReplaceWords = ['好用']; public function message() { return str_replace($this->bigDataFilterWords, $this->bigDataReplaceWords, $this->template->message()); } } // 客户端,发送接口,需要使用模板来进行短信发送 class Message { public $msgType = 'old'; public function send(MessageTemplate $mt) { // 发送出去咯 if ($this->msgType == 'old') { echo '面向内网用户发送' . $mt->message() . PHP_EOL; } else if ($this->msgType == 'new') { echo '面向全网用户发送' . $mt->message() . PHP_EOL; } } } $template = new CouponMessageTemplate(); $message = new Message(); // 老系统,用不着过滤,只有内部用户才看得到 $message->send($template); // 新系统,面向全网发布的,需要过滤一下内容哦 $message->msgType = 'new'; $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中文網其他相關文章!

PHP用於構建動態網站,其核心功能包括:1.生成動態內容,通過與數據庫對接實時生成網頁;2.處理用戶交互和表單提交,驗證輸入並響應操作;3.管理會話和用戶認證,提供個性化體驗;4.優化性能和遵循最佳實踐,提升網站效率和安全性。

PHP在數據庫操作和服務器端邏輯處理中使用MySQLi和PDO擴展進行數據庫交互,並通過會話管理等功能處理服務器端邏輯。 1)使用MySQLi或PDO連接數據庫,執行SQL查詢。 2)通過會話管理等功能處理HTTP請求和用戶狀態。 3)使用事務確保數據庫操作的原子性。 4)防止SQL注入,使用異常處理和關閉連接來調試。 5)通過索引和緩存優化性能,編寫可讀性高的代碼並進行錯誤處理。

在PHP中使用預處理語句和PDO可以有效防範SQL注入攻擊。 1)使用PDO連接數據庫並設置錯誤模式。 2)通過prepare方法創建預處理語句,使用佔位符和execute方法傳遞數據。 3)處理查詢結果並確保代碼的安全性和性能。

PHP和Python各有優劣,選擇取決於項目需求和個人偏好。 1.PHP適合快速開發和維護大型Web應用。 2.Python在數據科學和機器學習領域佔據主導地位。

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

PHP可以輕鬆創建互動網頁內容。 1)通過嵌入HTML動態生成內容,根據用戶輸入或數據庫數據實時展示。 2)處理表單提交並生成動態輸出,確保使用htmlspecialchars防XSS。 3)結合MySQL創建用戶註冊系統,使用password_hash和預處理語句增強安全性。掌握這些技巧將提升Web開發效率。

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

PHP仍然具有活力,其在現代編程領域中依然佔據重要地位。 1)PHP的簡單易學和強大社區支持使其在Web開發中廣泛應用;2)其靈活性和穩定性使其在處理Web表單、數據庫操作和文件處理等方面表現出色;3)PHP不斷進化和優化,適用於初學者和經驗豐富的開發者。


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

SublimeText3漢化版
中文版,非常好用

Dreamweaver Mac版
視覺化網頁開發工具

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

Atom編輯器mac版下載
最受歡迎的的開源編輯器