作为开始,我们建立一个普通的可以被扩展产生具体的特定装饰器的WidgetDecorator类。至少WidgetDecorator类应该能够在它的构造函数中接受一个组件,并复制公共方法paint()。
class WidgetDecorator { var $widget; function WidgetDecorator(&$widget) { $this->widget =& $widget; } function paint() { return $this->widget->paint(); } } |
为建立一个标签(lable),需要传入lable的内容,以及原始的组件:
class Labeled extends WidgetDecorator { var $label; function Labeled($label, &$widget) { $this->label = $label; $this->WidgetDecorator($widget); } } |
有标签的组件也需要复制paint()方法,并将标签信息增加到输出中:
class Labeled extends WidgetDecorator { var $label; function Labeled($label, &$widget) { $this->label = $label; $this->WidgetDecorator($widget); } function paint() { return ‘<b>’.$this->label.’:</b> ‘.$this->widget->paint(); } } |
你可以用一个测试检验它:
class WidgetTestCase extends UnitTestCase { function testLabeled() { $text =& new Labeled( ‘Email’ ,new TextInput(‘email’)); $output = $text->paint(); 208 The Decorator Pattern $this->assertWantedPattern(‘~^<b>Email:</b> <input~i’, $output); } } |
我们已经看到TextInput和Labeled类的能力,你可以装配一个类整体来管理表单(form)。
FormHandler类有一个静态的build()方法从表单的各种元素创建一个部件的数组。
class FormHandlerTestCase extends UnitTestCase { function testBuild() { $this->assertIsA($form = FormHandler::build(new Post), ‘Array’); $this->assertEqual(3, count($form)); $this->assertIsA($form[1], ‘Labeled’); $this->assertWantedPattern(‘~email~i’, $form[2]->paint()); } } |
实现FormHandler 的代码:
class FormHandler { function build() { return array( new Labeled(‘First Name’, new TextInput(‘fname’)) ,new Labeled(‘Last Name’, new TextInput(‘lname’)) ,new Labeled(‘Email’, new TextInput(‘email’)) ); } } |
现在,这段代码并不能工作—没有通过$_post提交的数据。因为这段代码必须要使用一个MockObject对象 (参见第6章)测试,现在我们可以将$_post数据包装在一个类似哈希的对象中—与Registry(参见第五章)类似,或者模仿WACT的DataSource从Specification pattern
class Post { var $store = array(); function get($key) { if (array_key_exists($key, $this->store)) return $this->store[$key]; } function set($key, $val) { $this->store[$key] = $val; } } |
想更方便的话,你可以使用Factory模式或者自动填充的方法来从$_POST里面提取关键字。
class Post { // ... function &autoFill() { $ret =& new Post; foreach($_POST as $key => $value) { $ret->set($key, $value); } return $ret; } } |
使用这个Post类,你可以编辑你的FormHandler::build() 方法,默认使用已经存在的$_post数据:
class FormHandler { function build(&$post) { return array( new Labeled(‘First Name’ , new TextInput(‘fname’, $post->get(‘fname’))) ,new Labeled(‘Last Name’ , new TextInput(‘lname’, $post->get(‘lname’))) ,new Labeled(‘Email’ , new TextInput(‘email’, $post->get(‘email’))) ); } } |
现在你可以创建一个php脚本使用FormHandler类来产生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> |
现在,你已经拥有了一个提交给它自身并且能保持posted数据的表单处理(form handler) 类。
延伸阅读:
从魔兽看PHP设计模式
《PHP设计模式介绍》导言
PHP设计模式介绍 第一章 编程惯用法
PHP设计模式介绍 第二章 值对象模式
PHP设计模式介绍 第三章 工厂模式
PHP设计模式介绍 第四章 单件模式
PHP设计模式介绍 第五章 注册模式
PHP设计模式介绍 第六章 伪对象模式
PHP设计模式介绍 第七章 策略模式
PHP设计模式介绍 第八章 迭代器模式