《PHP設(shè)計(jì)模式介紹》第十二章 裝飾器模式(4)_PHP教程
推薦:《PHP設(shè)計(jì)模式介紹》第十一章 代理模式因?yàn)槟硞(gè)對(duì)象消耗太多資源,而且你的代碼并不是每個(gè)邏輯路徑都需要此對(duì)象, 你曾有過延遲創(chuàng)建對(duì)象的想法嗎 ( if和else就是不同的兩條邏輯路徑) ? 你有想過限制訪問某個(gè)對(duì)象,也就是說,提供一組方法
現(xiàn)在。我們繼續(xù)為表單添加一些驗(yàn)證機(jī)制。方法是編輯另一個(gè)組件裝飾器類來表達(dá)一個(gè)“invalid”狀態(tài)并擴(kuò)展FormHandler類增加一個(gè)validate方法以處理組件示例數(shù)組。如果組件非法(“invalid”),我們通過一個(gè)“invalid”類將它包裝在<span>元素中。這里是一個(gè)證明這個(gè)目標(biāo)的測(cè)試
| class WidgetTestCase extends UnitTestCase { // ... function testInvalid() { $text =& new Invalid(new TextInput(‘email’)); $output = $text->paint(); $this->assertWantedPattern( ‘~^<span class=”invalid”><input[^>] ></span>$~i’, $output); } } |
這里是Invalid WidgetDecorator子類:
//代碼Here’s the Invalid WidgetDecorator subclass:
| class Invalid extends WidgetDecorator { function paint() { eturn ‘<span class=”invalid”>’.$this->widget->paint().’</span>’; } } |
裝飾器的一個(gè)有點(diǎn)是你可以將他們串在一起(使用)。Invalid裝飾器僅僅知道:它正在包裝一個(gè)組件:它不必關(guān)心組件是否是一個(gè)TextInput, Select,或者是一個(gè)有標(biāo)簽的被裝飾版本的組件 。
這導(dǎo)致了下一個(gè)合理的測(cè)試用例:
| class WidgetTestCase extends UnitTestCase { // ... function testInvalidLabeled() { $text =& new Invalid( new Labeled( ‘Email’ ,new TextInput(‘email’))); $output = $text->paint(); $this->assertWantedPattern(‘~<b>Email:</b> <input~i’, $output); $this->assertWantedPattern( ‘~^<span class=”invalid”>.*</span>$~i’, $output); } } |
有了Invalid裝飾器,我們來處理FormHandler::validate() 方法:
| class FormHandlerTestCase extends UnitTestCase { // ... function testValidateMissingName() { $post =& new Post; $post->set(‘fname’, ‘Jason’); $post->set(‘email’, ‘[email protected]’); $form = FormHandler::build($post); $this->assertFalse(FormHandler::validate($form, $post)); $this->assertNoUnwantedPattern(‘/invalid/i’, $form[0]->paint()); $this->assertWantedPattern(‘/invalid/i’, $form[1]->paint()); $this->assertNoUnwantedPattern(‘/invalid/i’, $form[2]->paint()); } } |
這個(gè)測(cè)試捕獲(包含)了所有的基本方面:建立一個(gè)Post實(shí)例的存根,使用它建立一個(gè)組件集合,然后將集合傳送給validate方法。
| class FormHandler { function validate(&$form, &$post) { // first name required if (!strlen($post->get(‘fname’))) { $form[0] =& new Invalid($form[0]);} // last name required if (!strlen($post->get(‘lname’))) { $form[1] =& new Invalid($form[1]); } } } |
不協(xié)調(diào)的代碼
當(dāng)我看這段代碼時(shí),我發(fā)現(xiàn)了兩個(gè)不協(xié)調(diào)之處:通過數(shù)字索引訪問表單元素,需要傳遞$_post數(shù)組。給validation方法。在以后的重構(gòu)中,最好是創(chuàng)建一個(gè)組件集合用一個(gè)以表單元素名字索引的關(guān)聯(lián)數(shù)組表示或者用一個(gè)Registry模式作為更合理的一步。你也可以給類Widget增加一個(gè)方法返回它的
當(dāng)前數(shù)值,取消需要傳遞$_Post實(shí)例給Widget集合的構(gòu)造函數(shù)。所有這些都超出了這個(gè)例子目的的范圍。
為了驗(yàn)證目的,我們繼續(xù)增加一個(gè)簡(jiǎn)單的 正則方法(regex)來驗(yàn)證email地址:
| class FormHandlerTestCase extends UnitTestCase { // ... function testValidateBadEmail() { $post =& new Post; $post->set(‘fname’, ‘Jason’); $post->set(‘lname’, ‘Sweat’); $post->set(‘email’, ‘jsweat_php AT yahoo DOT com’); $form = FormHandler::build($post); $this->assertFalse(FormHandler::validate($form, $post)); $this->assertNoUnwantedPattern(‘/invalid/i’, $form[0]->paint()); $this->assertNoUnwantedPattern(‘/invalid/i’, $form[1]->paint()); $this->assertWantedPattern(‘/invalid/i’, $form[2]->paint()); } } |
實(shí)現(xiàn)這個(gè)簡(jiǎn)單的email驗(yàn)證的代碼如下:
//代碼
| class FormHandler { function validate(&$form, &$post) { // first name required if (!strlen($post->get(‘fname’))) { $form[0] =& new Invalid($form[0]);} // last name required if (!strlen($post->get(‘lname’))) { $form[1] =& new Invalid($form[1]); } // email has to look real if (!preg_match(‘~\w @(\w \.) \w ~’ ,$post->get(‘email’))) { $form[2] =& new Invalid($form[2]); } } } |
你也可以創(chuàng)建一個(gè)測(cè)試用例以驗(yàn)證form表單何時(shí)有效://代碼
| class FormHandlerTestCase extends UnitTestCase { // ... function testValidate() { $post =& new Post; $post->set(‘fname’, ‘Jason’); $post->set(‘lname’, ‘Sweat’); $post->set(‘email’, ‘[email protected]’); $form = FormHandler::build($post); $this->assertTrue(FormHandler::validate($form, $post)); $this->assertNoUnwantedPattern(‘/invalid/i’, $form[0]->paint()); $this->assertNoUnwantedPattern(‘/invalid/i’, $form[1]->paint()); $this->assertNoUnwantedPattern(‘/invalid/i’, $form[2]->paint()); } } |
這又提出了在本方法內(nèi)追蹤任何驗(yàn)證失敗的需求,因此它可以返回true如果所有的都合格。
分享:《PHP設(shè)計(jì)模式介紹》第十章 規(guī)范模式在一個(gè)應(yīng)用軟件的成型過程中,一些意想不到的商業(yè)邏輯到處出現(xiàn)。比如,基于價(jià)格的考慮,這個(gè)任務(wù)必須減少項(xiàng)目;而那個(gè)任務(wù)也因?yàn)殇N售稅而必須選擇合適的比率;而其它的任務(wù)也必須因?yàn)槠渌奶貏e
- PHPNOW安裝Memcached擴(kuò)展方法詳解
- php記錄頁(yè)面代碼執(zhí)行時(shí)間
- PHP中獎(jiǎng)概率的抽獎(jiǎng)算法程序代碼
- apache設(shè)置靜態(tài)文件緩存方法介紹
- php對(duì)圖像的各種處理函數(shù)代碼小結(jié)
- PHP 關(guān)于訪問控制的和運(yùn)算符優(yōu)先級(jí)介紹
- 關(guān)于PHP語言構(gòu)造器介紹
- php/js獲取客戶端mac地址的實(shí)現(xiàn)代碼
- php5.5新數(shù)組函數(shù)array_column使用
- PHP preg_match的匹配多國(guó)語言的技巧
- php 中序列化和json使用介紹
- php采集文章中的圖片獲取替換到本地
PHP教程Rss訂閱編程教程搜索
PHP教程推薦
- PHP中使用XML-RPC構(gòu)造Web Service簡(jiǎn)單入門
- 淺析關(guān)于cookie和session
- 關(guān)于php 接口問題(php接口主要也就是運(yùn)用curl,curl函數(shù))
- 怎樣把握技巧開發(fā)PHP網(wǎng)站
- 用PHP5的SimpleXML解析XML文檔
- 解析PHP安裝十大問題
- 在PHP中使用MVC模式進(jìn)行開發(fā)
- 淺談PHP開發(fā)團(tuán)隊(duì)的管理之道
- Apache實(shí)現(xiàn)Web Server負(fù)載均衡詳解(不考慮Session版)
- PHP技術(shù)進(jìn)階 用PHP處理多個(gè)同名復(fù)選框
- 相關(guān)鏈接:
- 教程說明:
PHP教程-《PHP設(shè)計(jì)模式介紹》第十二章 裝飾器模式(4)
。