php教程:php设计模式介绍之规范模式(5)
下面这个例子演示了如何为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)你看一眼就会明白,根本无需深入详细的钻研代码。这也是规范模式的优点之一吧。
到现在为止,你应该很清楚的明白规范模式就如一个接口。使用PHP5明确的表示出这个规范模式:
interface Specification {
public function isSatisfiedBy($datasource);
}
我们把这些基本的模块按照一定的格式集中起来,这甚至是非常有用的。因为从一个规范类的方法isSatisfiedBy()中返回的结果是一个布尔值(boolean),把这些布尔值运用到具体不同的规范类的效果都是相当好的。
为了实现逻辑与,我们创建一个类,把两个具体的规范实例类组合起来,当给出的数据源参数同时满足给定的条件后就返回true。
class AndSpecification implements Specification {
protected $spec;
protected $andSpec;
public function __construct($spec, $andSpec) {
$this->spec = $spec;
$this->andSpec = $andSpec;
function isSatisfiedBy($datasource) {
return ($this->spec->isSatisfiedBy($datasource)
&& $this->andSpec->isSatisfiedBy($datasource));
}
你也可以类似的实现逻辑或。
class OrSpecification implements Specification {
protected $spec;
protected $orSpec;
public function __construct($spec, $orSpec) {
$this->spec = $spec;
$this->orSpec = $orSpec;
function isSatisfiedBy($datasource) {
return ($this->spec->isSatisfiedBy($datasource)
|| $this->orSpec->isSatisfiedBy($datasource));
}
利用已经给出的“逻辑”规范和最初的一些规规范集合,你可以实现一些复杂的验证。
class PolicyFactory {
public function createJasonPolicy() {
$name_jason = new FieldEqualSpecification(‘name’, ‘Jason’);
$age_at_least_thirty =
new FieldGreaterThanOrEqualSpecification(‘age’, 30);
$male = new FieldEqualSpecification(‘sex’, ‘male’);
$jasons_email = new OrSpecification(
new FieldEqualSpecification(‘email’, ‘jsweat_php@yahoo.com’)
, new FieldEqualSpecification(‘email’,
‘jsweat@users.sourceforge.net’));
return new AndSpecification(
$name_jason, new AndSpecification(
$age_at_least_thirty,
new AndSpecification($male, $jasons_email)
));
}
}