当你的应用程序必须加工处理一个表单,你可以先把$_POST过来的数据值装载到数据源DataSource,然后使用参数化规范来完成表单的验证。(同样的方法也可以用到配置文件上,把配置文件的数据装载到DataSource数据源,然后使用规范来验证)。
现在,让我们构造一个参数化规范的示例类,主要用来搭建一个数据块。首先,我们要建一个规范,这个规范得满足“某一个字段和指定的值等价”的条件。
class FieldEqualSpecification { protected $field; protected $value; public function __construct($field, $value) { $this->field = $field; $this->value = $value; } public function isSatisfiedBy($datasource) { return ($datasource->get($this->field) == $this->value); } } |
这个思路是很简单的:在构造(construction)期间,存储一个字段和它期望的值,从数据源(DataSource)中获取到期望的值传递到方法isSatisfiedBy(),然后比较。
为了测试这个规范,写一个测试实例来演示这个数据源(DataSource):
class SpecificationsTestCase extends UnitTestCase { protected $ds; function setup() { $this->ds = new DataSource; $this->ds->set(‘name’, ‘Jason’); $this->ds->set(‘age’, 34); $this->ds->set(‘email’, ‘jsweat_php@yahoo.com’); $this->ds->set(‘sex’, ‘male’); } } |
在上面的例子里,方法setup()创建了一个数据源对象,并设置了相应的属性。这个测试还包含一个方法,这个方法要么返回pass要么返回fail。
class SpecificationsTestCase extends UnitTestCase { // ... function TestFieldEqualSpecification() { $name_jason = new FieldEqualSpecification(‘name’, ‘Jason’); $this->assertTrue($name_jason->isSatisfiedBy($this->ds)); $sex_other = new FieldEqualSpecification(‘sex’, ‘other’); $this->assertFalse($sex_other->isSatisfiedBy($this->ds)); } } |
通常在评估字符串的时候,一个正则表达式比一系列严格的比较关系能够更好的帮助你来定义你的需求。那么,让我们在FieldMatchSpecification中使用正则表达式来匹配我们的规范工具集。
class FieldMatchSpecification { |
下面这个例子演示了如何为FieldMatchSpecification字段匹配规范书写测试实例。
class SpecificationsTestCase extends UnitTestCase { // ... function TestFieldMatchSpecification() { $valid_email = new FieldMatchSpecification( ‘email’, ‘/^[^\s@]+@[^\s.]+(?:\.[^\s.]+)+/’); $this->assertTrue($valid_email->isSatisfiedBy($this->ds)); $name_ten_letters = new FieldMatchSpecification( ‘name’, ‘/^\w{10}$/’); $this->assertFalse($name_ten_letters->isSatisfiedBy($this->ds)); } } |
上面例子中的email正则要求“在@前是一串不包含空格、@的字符,在@后是两组或者两组以上不包含可个空格或者句点的字符串,这些字符串之间由句点间隔着”。而变量$name_ten_letters规范要求输入的值必须恰好是由10个字符组成。
注:正则表达式
有许多书籍单独开一章来讲解正则表达式,甚至有些整本书都在讨论这个话题(译者注:作者是为了说明正则表达式的重要性和难度)。所以,请认识到上面的代码只是一个过于简单化的例子,而不是一个检查email的完善的正则表达式。
下面让我们搭建最后一个具体的规范用来检验一个字段值是否大于或者等于对应的值。我们毫无疑问的把它命名为FieldGreaterThanOrEqualSpecification.。
class FieldGreaterThanOrEqualSpecification { protected $field; protected $value; public function __construct($field, $value) { $this->field = $field; $this->value = $value; } public function isSatisfiedBy($datasource) { return ($datasource->get($this->field) >= $this->value); } } |
这里没有太多的不可思议的:在构造器里面存储相应的要被比较的字段和值,然后在方法isSatisfiedBy()里面验证提取出来的字段。
下面是一个测试实例,用来演示如何应用FieldGreaterThanOrEqualSpecification。
class SpecificationsTestCase extends UnitTestCase { // ... function TestFieldGreaterThanOrEqualSpecification() { $adult = new FieldGreaterThanOrEqualSpecification(‘age’, 18); $presidential_age = new FieldGreaterThanOrEqualSpecification(‘age’, 35); $this->assertTrue($adult->isSatisfiedBy($this->ds)); $this->assertFalse($presidential_age->isSatisfiedBy($this->ds)); } } |
你是否已经注意到在规范对象被标识上合理的名称时候,这些代码是如何开始证明自己的吗?你是否能够通过规范对象的名称来理解到代码的相应的功能? $adult->isSatisfiedBy($something)你看一眼就会明白,根本无需深入详细的钻研代码。这也是规范模式的优点之一吧。
延伸阅读:
从魔兽看PHP设计模式
《PHP设计模式介绍》导言
PHP设计模式介绍 第一章 编程惯用法
PHP设计模式介绍 第二章 值对象模式
PHP设计模式介绍 第三章 工厂模式
PHP设计模式介绍 第四章 单件模式
PHP设计模式介绍 第五章 注册模式
PHP设计模式介绍 第六章 伪对象模式
PHP设计模式介绍 第七章 策略模式
PHP设计模式介绍 第八章 迭代器模式
PHP设计模式介绍 第九章 观测模式