日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

PHP設(shè)計模式(八)裝飾器模式Decorator實例詳解【結(jié)構(gòu)型】

瀏覽:227日期:2022-09-10 14:43:28

本文實例講述了PHP設(shè)計模式:裝飾器模式Decorator。分享給大家供大家參考,具體如下:

1. 概述

若你從事過面向?qū)ο箝_發(fā),實現(xiàn)給一個類或?qū)ο笤黾有袨?,使用繼承機制,這是所有面向?qū)ο笳Z言的一個基本特性。如果已經(jīng)存在的一個類缺少某些方法,或者須要給方法添加更多的功能(魅力),你也許會僅僅繼承這個類來產(chǎn)生一個新類—這建立在額外的代碼上。

通過繼承一個現(xiàn)有類可以使得子類在擁有自身方法的同時還擁有父類的方法。但是這種方法是靜態(tài)的,用戶不能控制增加行為的方式和時機。如果 你希望改變一個已經(jīng)初始化的對象的行為,你怎么辦?或者,你希望繼承許多類的行為,改怎么辦?前一個,只能在于運行時完成,后者顯然時可能的,但是可能會導(dǎo)致產(chǎn)生大量的不同的類—可怕的事情。

2. 問題

你如何組織你的代碼使其可以容易的添加基本的或者一些很少用到的 特性,而不是直接不額外的代碼寫在你的類的內(nèi)部?

3. 解決方案

裝飾器模式: 動態(tài)地給一個對象添加一些額外的職責或者行為。就增加功能來說, Decorator模式相比生成子類更為靈活。

裝飾器模式提供了改變子類的靈活方案。裝飾器模式在不必改變原類文件和使用繼承的情況下,動態(tài)的擴展一個對象的功能。它是通過創(chuàng)建一個包裝對象,也就是裝飾來包裹真實的對象。

當用于一組子類時,裝飾器模式更加有用。如果你擁有一族子類(從一個父類派生而來),你需要在與子類獨立使用情況下添加額外的特性,你可以使用裝飾器模式,以避免代碼重復(fù)和具體子類數(shù)量的增加。

4. 適用性

以下情況使用Decorator模式

1)• 在不影響其他對象的情況下,以動態(tài)、透明的方式給單個對象添加職責。

2)• 處理那些可以撤消的職責。

3)• 當不能采用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴展,

為支持每一種組合將產(chǎn)生大量的子類,使得子類數(shù)目呈爆炸性增長。

另一種情況可能是因為類定義被隱藏,或類定義不能用于生成子類。

5. 結(jié)構(gòu)

uml如圖:

PHP設(shè)計模式(八)裝飾器模式Decorator實例詳解【結(jié)構(gòu)型】

6.構(gòu)建模式的組成

抽象組件角色(Component):定義一個對象接口,以規(guī)范準備接受附加責任的對象,

即可以給這些對象動態(tài)地添加職責。

具體組件角色(ConcreteComponent) :被裝飾者,定義一個將要被裝飾增加功能的類。

可以給這個類的對象添加一些職責

抽象裝飾器(Decorator):維持一個指向構(gòu)件Component對象的實例,

并定義一個與抽象組件角色Component接口一致的接口

具體裝飾器角色(ConcreteDecorator):向組件添加職責。

7. 效果

裝飾模式的特點:

(1) 裝飾對象和真實對象有相同的接口。這樣客戶端對象就可以以和真實對象相同的方式和裝飾對象交互。(2) 裝飾對象包含一個真實對象的索引(reference)(3) 裝飾對象接受所有的來自客戶端的請求。它把這些請求轉(zhuǎn)發(fā)給真實的對象。(4) 裝飾對象可以在轉(zhuǎn)發(fā)這些請求以前或以后增加一些附加功能。這樣就確保了在運行時,不用修改給定對象的結(jié)構(gòu)就可以在外部增加附加的功能。在面向?qū)ο蟮脑O(shè)計中,通常是通過繼承來實現(xiàn)對給定類的功能擴展。

Decorator模式至少有兩個主要優(yōu)點和兩個缺點:

1) 比靜態(tài)繼承更靈活: 與對象的靜態(tài)繼承(多重繼承)相比, Decorator模式提供了更加靈活的向?qū)ο筇砑勇氊煹姆绞?。可以用添加和分離的方法,用裝飾在運行時刻增加和刪除職責。相比之下,繼承機制要求為每個添加的職責創(chuàng)建一個新的子類。這會產(chǎn)生許多新的類,并且會增加系統(tǒng)的復(fù)雜度。此外,為一個特定的Component類提供多個不同的 Decorator類,這就使得你可以對一些職責進行混合和匹配。使用Decorator模式可以很容易地重復(fù)添加一個特性。2) 避免在層次結(jié)構(gòu)高層的類有太多的特征 Decorator模式提供了一種“即用即付”的方法來添加職責。它并不試圖在一個復(fù)雜的可定制的類中支持所有可預(yù)見的特征,相反,你可以定義一個簡單的類,并且用 Decorator類給它逐漸地添加功能??梢詮暮唵蔚牟考M合出復(fù)雜的功能。這樣,應(yīng)用程序不必為不需要的特征付出代價。同時更易于不依賴于 Decorator所擴展(甚至是不可預(yù)知的擴展)的類而獨立地定義新類型的 Decorator。擴展一個復(fù)雜類的時候,很可能會暴露與添加的職責無關(guān)的細節(jié)。3) Decorator與它的Component不一樣 Decorator是一個透明的包裝。如果我們從對象標識的觀點出發(fā),一個被裝飾了的組件與這個組件是有差別的,因此,使用裝飾不應(yīng)該依賴對象標識。4) 有許多小對象 采用Decorator模式進行系統(tǒng)設(shè)計往往會產(chǎn)生許多看上去類似的小對象,這些對象僅僅在他們相互連接的方式上有所不同,而不是它們的類或是它們的屬性值有所不同。盡管對于那些了解這些系統(tǒng)的人來說,很容易對它們進行定制,但是很難學習這些系統(tǒng),排錯也很困難。

8. 實現(xiàn)

使用《php設(shè)計模式》里面的例子。

看看以下例子,你可以更好的理解這種觀點。考慮一個建立在組件概念上的“form”表單庫,在那里你需要為每一個你想要表現(xiàn)的表單控制類型建立一個類。這種類圖可以如下所示:

Select and TextInput類是組件類的子類。假如你想要增加一個“l(fā)abeled”帶標簽的組件—一個輸入表單告訴你要輸入的內(nèi)容。因為任何一個表單都可能需要被標記,你可能會象這樣繼承每一個具體的組件:

PHP設(shè)計模式(八)裝飾器模式Decorator實例詳解【結(jié)構(gòu)型】

上面的類圖看起來并不怎么壞,下面讓我們再增加一些特性。表單驗證階段,你希望能夠指出一個表單控制是否合法。你為非法控制使用的代碼又一次繼承其它組件,因此又需要產(chǎn)生大量的子類:

PHP設(shè)計模式(八)裝飾器模式Decorator實例詳解【結(jié)構(gòu)型】

這個類看起來并不是太壞,所以讓我們增加一些新的功能。在結(jié)構(gòu)有效性確認中你需要指出結(jié)構(gòu)是否是有效的。你需要讓你檢驗有效性的代碼也可以應(yīng)用到其它部件,這樣不用再更多的子類上進行有效性驗證。

PHP設(shè)計模式(八)裝飾器模式Decorator實例詳解【結(jié)構(gòu)型】

這里子類溢出并不是唯一的問題。想一想那些重復(fù)的代碼,你需要重新設(shè)計你的整個類層次。有沒有更好的方法!確實,裝飾器模式是避免這種情況的好方法。

裝飾器模式結(jié)構(gòu)上類似與代理模式。一個裝飾器對象保留有對對象的引用,而且忠實的重新建立被裝飾對象的公共接口。裝飾器也可以增加方法,擴展被裝飾對象的接口,任意重載方法,甚至可以在腳本執(zhí)行期間有條件的重載方法。

為了探究裝飾器模式,讓我們以前面討論過的表單組件庫為例,并且用裝飾器模式而不是繼承,實現(xiàn)“l(fā)able”和“invalidation”兩個特性。

樣本代碼:

組件庫包含哪些特性?

1.容易創(chuàng)建表單元素

2.將表單元素以html方式輸出

3.在每個元素上實現(xiàn)簡單的驗證

本例中,我們創(chuàng)建一個包含姓,名,郵件地址,輸入項的表單。所有的區(qū)域都是必須的,而且E-mail必須看起來是有效的E—mail地址。用HTML語言表示,表單的代碼象下面所示:

<form action=”formpage.php” method=”post”><b>First Name:</b> <input type=”text” name=”fname” value=””><br><b>Last Name:</b> <input type=”text” name=”lname” value=””><br><b>Email:</b> <input type=”text” name=”email” value=””><br><input type=”submit” value=”Submit”></form>

增加一些css樣式后,表單渲染出來如下圖所示:

PHP設(shè)計模式(八)裝飾器模式Decorator實例詳解【結(jié)構(gòu)型】

我們使用裝飾器代碼:

<?php /** * 裝飾器模式的組成: * 抽象組件角色(Component):定義一個對象接口,以規(guī)范準備接受附加責任的對象,即可以給這些對象動態(tài)地添加職責。 * 具體組件角色(ConcreteComponent) :被裝飾者,定義一個將要被裝飾增加功能的類。可以給這個類的對象添加一些職責。 * 抽象裝飾器(Decorator):維持一個指向構(gòu)件Component對象的實例,并定義一個與抽象組件角色Component接口一致的接口。 * 具體裝飾器角色(ConcreteDecorator): 向組件添加職責。 * @author guisu * @version 1.0 */ /** * 抽象組件角色(Component) * */class ComponentWidget { function paint() { return $this->_asHtml(); }} /** * * 具體組件角色(ConcreteComponent): * 讓我們以一個基本的text輸入組件開始。它(組件)必須要包含輸入?yún)^(qū)域的名字(name)而且輸入內(nèi)容可以以HTML的方式渲染。 * */class ConcreteComponentTextInput extends ComponentWidget { protected $_name; protected $_value; function TextInput($name, $value=’’) { $this->_name = $name; $this->_value = $value; } function _asHtml() { return ’<input type='text' name='’.$this->_name.’' value='’.$this->_value.’'>’; } }/** * 抽象裝飾器(Decorator):維持一個指向構(gòu)件Component對象的實例,并定義一個與抽象組件角色Component接口一致的接口。 * * 我們進入有能夠統(tǒng)一增加(一些特性)能力的裝飾器模式。 * 作為開始,我們建立一個普通的可以被擴展產(chǎn)生具體的特定裝飾器的WidgetDecorator類。至少WidgetDecorator類應(yīng)該能夠在它的構(gòu)造函數(shù)中接受一個組件, * 并復(fù)制公共方法paint() * */class WidgetDecorator { protected $_widget; function __construct( &$widget) { $this->_widget = $widget; } function paint() { return $this->_widget->paint(); } }/** * 具體裝飾器角色(ConcreteDecorator): * 為建立一個標簽(lable),需要傳入lable的內(nèi)容,以及原始的組件 * 有標簽的組件也需要復(fù)制paint()方法 * */ class ConcreteDecoratorLabeled extends WidgetDecorator { protected $_label; function __construct($label, &$widget) { $this->_label = $label; parent::__construct($widget); } function paint() { return ’<b>’.$this->_label.’:</b> ’.$this->_widget->paint(); } } /** * 實現(xiàn) * */class FormHandler { function build(&$post) { return array( new ConcreteDecoratorLabeled(’First Name’, new ConcreteComponentTextInput(’fname’, $post->get(’fname’))) ,new ConcreteDecoratorLabeled(’Last Name’, new ConcreteComponentTextInput(’lname’, $post->get(’lname’))) ,new ConcreteDecoratorLabeled(’Email’, new ConcreteComponentTextInput(’email’, $post->get(’email’))) ); } } /** * 通過$_post提交的數(shù)據(jù) */ class Post { private $store = array(); function get($key) { if (array_key_exists($key, $this->store)) return $this->store[$key]; } function set($key, $val) { $this->store[$key] = $val; } static function autoFill() { $ret = new self(); foreach($_POST as $key => $value) { $ret->set($key, $value); } return $ret; } }?>

以創(chuàng)建一個php腳本使用FormHandler類來產(chǎn)生HTML表單:

<form action=”formpage.php” method=”post”><?php$post =& Post::autoFill();$form = FormHandler::build($post);foreach($form as $widget) { echo $widget->paint(), '<br>n';}?><input type=”submit” value=”Submit”></form>

現(xiàn)在,你已經(jīng)擁有了個提交給它自身并且能保持posted數(shù)據(jù)的表單處理(form handler) 類。現(xiàn)在。我們繼續(xù)為表單添加一些驗證機制。方法是編輯另一個組件裝飾器類來表達一個“invalid”狀態(tài)并擴展FormHandler類增加一個validate()方法以處理組件示例數(shù)組。如果組件非法(“invalid”),我們通過一個“invalid”類將它包裝在<span>元素中。

<?phpclass Invalid extends WidgetDecorator { function paint() { return ’<span class='invalid'>’.$this->widget->paint().’</span>’; }}

FormHandler新加方法validate:

/** * 實現(xiàn) * */class FormHandler { function build(&$post) { return array( new ConcreteDecoratorLabeled(’First Name’, new ConcreteComponentTextInput(’fname’, $post->get(’fname’))) ,new ConcreteDecoratorLabeled(’Last Name’, new ConcreteComponentTextInput(’lname’, $post->get(’lname’))) ,new ConcreteDecoratorLabeled(’Email’, new ConcreteComponentTextInput(’email’, $post->get(’email’))) ); } function validate(&$form, &$post) { $valid = true; // first name required if (!strlen($post->get(’fname’))) { $form[0] =& new Invalid($form[0]); $valid = false; } // last name required if (!strlen($post->get(’lname’))) { $form[1] =& new Invalid($form[1]); $valid = false;} // email has to look real if (!preg_match(’~w+@(w+.)+w+~’ ,$post->get(’email’))) { $form[2] =& new Invalid($form[2]); $valid = false; } return $valid; }}

最后結(jié)果:

<html><head><title>Decorator Example</title><style type='text/css'>.invalid {color: red; }.invalid input { background-color: red; color: yellow; }#myform input { position: absolute; left: 110px; width: 250px; font-weight: bold;}</style></head><body><form action='<?php echo $_SERVER['PHP_SELF']; ?>' method='post'><div id='myform'><?php $pos =& Post::autoFill();$form = FormHandler::build($post);if ($_POST) { FormHandler::validate($form, $post);}foreach($form as $widget) { echo $widget->paint(), '<br>n';}?> </div><input type='submit' value='Submit'></form></body></html>9. 裝飾器模式與其他相關(guān)模式

1)Adapter 模式:Decorator模式不同于Adapter模式,因為裝飾僅改變對象的職責而不改變它的接口;而適配器將給對象一個全新的接口。

2)Composite模式:可以將裝飾視為一個退化的、僅有一個組件的組合。然而,裝飾僅給對象添加一些額外的職責—它的目的不在于對象聚集。

3)Strategy模式:用一個裝飾你可以改變對象的外表;而Strategy模式使得你可以改變對象的內(nèi)核。這是改變對象的兩種途徑。

10.總結(jié)

1)使用裝飾器設(shè)計模式設(shè)計類的目標是: 不必重寫任何已有的功能性代碼,而是對某個基于對象應(yīng)用增量變化。

2) 裝飾器設(shè)計模式采用這樣的構(gòu)建方式: 在主代碼流中應(yīng)該能夠直接插入一個或多個更改或“裝飾”目標對象的裝飾器,

同時不影響其他代碼流。

3) Decorator模式采用對象組合而非繼承的手法,實現(xiàn)了在運行時動態(tài)的擴展對象功能的能力,

而且可以根據(jù)需要擴展多個功能,避免了單獨使用繼承帶來的“靈活性差”和“多子類衍生問題”。

同時它很好地符合面向?qū)ο笤O(shè)計原則中“優(yōu)先使用對象組合而非繼承”和“開放-封閉”原則。

也許裝飾器模式最重要的一個方面是它的超過繼承的能力?!皢栴}”部分展現(xiàn)了一個使用繼承的子類爆炸。

基于裝飾器模式的解決方案,UML類圖展現(xiàn)了這個簡潔靈活的解決方案。

更多關(guān)于PHP相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《php面向?qū)ο蟪绦蛟O(shè)計入門教程》、《PHP數(shù)組(Array)操作技巧大全》、《PHP基本語法入門教程》、《PHP運算與運算符用法總結(jié)》、《php字符串(string)用法總結(jié)》、《php+mysql數(shù)據(jù)庫操作入門教程》及《php常見數(shù)據(jù)庫操作技巧匯總》

希望本文所述對大家PHP程序設(shè)計有所幫助。

標簽: PHP
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
亚洲五月婷婷| 日韩欧美一区二区三区在线视频| 国产一区日韩欧美| 日本а中文在线天堂| 久久婷婷久久| 模特精品在线| 日韩av午夜在线观看| 国产专区精品| 九九在线精品| 日韩精品成人| 中文在线免费视频| 五月天久久777| 日韩国产欧美视频| аⅴ资源天堂资源库在线| 亚洲福利专区| 亚洲男人在线| 国产一区二区三区四区五区 | 欧美日韩黄网站| 免费日韩成人| 女人天堂亚洲aⅴ在线观看| 色婷婷成人网| 天堂√8在线中文| 免费在线观看精品| 免费亚洲婷婷| 亚洲资源av| 久久香蕉精品香蕉| 不卡一区综合视频| 日本午夜精品视频在线观看| 98精品视频| 视频一区国产视频| 精品资源在线| 男女男精品网站| www.com.cn成人| 日韩精品免费视频人成| 香蕉成人av| 欧美日韩伊人| 欧美日韩国产亚洲一区| 久久精品国产福利| 蜜臀久久久久久久| 麻豆mv在线观看| 欧美片网站免费| 欧美日韩国产精品一区二区亚洲| 欧美国产不卡| 最新亚洲国产| 欧美精品日日操| 国产乱人伦精品一区| 久久久777| 国内一区二区三区| 日韩精品一区二区三区免费视频| 亚洲国产专区| 国产一区二区精品久| 亚洲免费观看高清完整版在线观| 久久免费黄色| 精品欧美日韩精品| 国产亚洲高清在线观看| 婷婷亚洲综合| 欧美gv在线| 久久中文精品| 日韩高清在线不卡| 欧美国产91| 日韩综合在线| 欧美黄色一区| 日本国产亚洲| 亚洲三区欧美一区国产二区| 欧美 日韩 国产精品免费观看| 国产欧美一区二区三区米奇| 在线视频精品| 99久久精品网站| 国产91在线播放精品| 日韩国产精品久久久| 日韩精品一二三区| 久久久亚洲一区| 国产精品a级| 麻豆视频一区| 黄色av一区| 久久天堂av| 国产拍在线视频| 国产不卡一区| 99成人在线| 日韩欧美不卡| 国产黄大片在线观看| 国产精品一二| 奇米777国产一区国产二区| 热久久免费视频| 国产一级久久| 亚洲在线观看| 日韩一级不卡| 黄色在线一区| 亚洲一区二区三区高清| 久久久久国产精品一区二区| 久久久久免费| 精品久久久久久久| 国产成人精品免费视| 久久精品网址| 美女高潮久久久| 精品国产麻豆| 亚洲一级少妇| 久久狠狠婷婷| 欧美在线资源| 亚洲精品综合| 国产精品亚洲四区在线观看| 国产视频一区二区在线播放| 国产欧美日韩视频在线| 日韩激情一区二区| 国产精品尤物| 久久免费精品| yellow在线观看网址| 日韩欧美少妇| 国产农村妇女精品一二区| 中文字幕亚洲精品乱码| 国产精品黄色片| 日韩高清一区二区| 精品视频一区二区三区在线观看| 色婷婷色综合| 欧美午夜不卡| 精品五月天堂| 国产欧美69| 精品久久影院| 国产一区久久| 精品国产欧美日韩一区二区三区| 日韩黄色在线观看| 欧美日韩亚洲国产精品| 欧美激情综合| 日韩中文字幕高清在线观看| 久久国产亚洲精品| 妖精视频成人观看www| 伊人久久一区| 欧美国产不卡| 久久91导航| 中文字幕一区二区三区日韩精品 | 久久麻豆视频| 国产a亚洲精品| 午夜国产精品视频| 日韩视频1区| 国产suv精品一区二区四区视频| 99久久夜色精品国产亚洲1000部| 亚洲综合精品| 久久影院资源站| 激情婷婷综合| 欧美日韩中文| 久久精品国产99久久| 日韩激情中文字幕| 电影91久久久| 午夜在线精品偷拍| 精品视频网站| 三上悠亚国产精品一区二区三区| 一区二区精彩视频| sm久久捆绑调教精品一区| 蜜桃传媒麻豆第一区在线观看| 久久婷婷国产| 日韩一区二区三区精品视频第3页| 国产精品久久久久久av公交车| 亚洲久久在线| 91免费精品国偷自产在线在线| 好看的av在线不卡观看| 日韩一区二区中文| 成人影视亚洲图片在线| 国产精品.xx视频.xxtv| 在线观看精品| 夜久久久久久| 亚洲婷婷在线| 亚洲18在线| 麻豆高清免费国产一区| 午夜欧美巨大性欧美巨大| 亚洲精品乱码| 欧洲一级精品| 国产日韩1区| 一区三区视频| 麻豆视频在线观看免费网站黄 | 国产三级一区| 国产亚洲在线观看| 精品一级视频| 婷婷精品在线观看| 欧美成人精品| 四季av一区二区凹凸精品| 日韩国产91| 久久国产精品久久w女人spa| 日韩在线欧美| 久久精品国产久精国产| 日韩不卡手机在线v区| 午夜在线一区| 伊人影院久久| 婷婷六月综合| 日韩在线二区| 中文av在线全新| 麻豆成人av在线| 国产欧美日韩在线一区二区 | 久久精品一区二区国产| 黑丝一区二区| а√天堂8资源中文在线| 久久黄色影视| 日本成人在线视频网站| 久久成人亚洲| 午夜一级在线看亚洲| 蜜桃成人av| 在线成人动漫av| 国产精品超碰| 亚洲二区三区不卡| 国产精品密蕾丝视频下载| 中文字幕一区二区三区日韩精品|