《PHP设计模式介绍》第十章 规范模式(3)_PHP教程
推荐:《PHP设计模式介绍》第九章 观测模式一些面向对象的编程方式,提供了一种构建对象间复杂网络互连的能力。当对象们连接在一起时,它们就可以相互提供服务和信息。 通常来说,当某个对象的状态发生改变时,你仍然需要对象之间能互
当你的应用程序必须加工处理一个表单,你可以先把$_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 { |
在这个例子里,这个字段对应的值和PCRE表达式都在构造的时候保存好了。然后方法isSatisfiedBy()从传递过来的数据源DataSource获取到这个字段,并且使用preg_match()方法来比较它的值是否满足对应的正则表达式。
下面这个例子演示了如何为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设计模式介绍》第八章 迭代器模式类中的面向对象编程封装应用逻辑。类,就是实例化的对象,每个单独的对象都有一个特定的身份和状态。单独的对象是一种组织代码的有用方法,但通常你会处理一组对象或者集合。 属性来自 SQL 查
- 相关链接:
- 教程说明:
PHP教程-《PHP设计模式介绍》第十章 规范模式(3)。