php教程:php设计模式介绍之规范模式(4)
现在让我们看看另外一个例子,在这个例子里面数据类型和规范都必须是非常的灵活易变的。
在web应用程序中,最常用也最让人发狂的一个问题就是确认表单输入(对表单输入数据的验证)。在软件开发过程中(甚至在开发过程外),表单是经常改变得,而且在大型的或者功能丰富的应用程序里面,表单的数量能够很快的增长。你可以创建一个唯一的对象来封装每一个表单,然后使用规范模式来确认每一个对象,但这绝对是一个持续的恶梦。
有没有一个方便的数据类型能够很容易的适应任何一个表单吗?如果有,那么有没有一个能够确认动态数据类型的方式呢?
上面每一个问题的答案显然是肯定的。
WEB应用程序组件工具箱(简称WACT)的数据源(DataSource)接口能够get(获取),set(设置),,并且动态的创建对象属性(有点类似PHP4的_GET()和_SET()方法),这些对象属性就是表单的封装操作手柄。(熟悉JAVA的读者可以把一个数据源(DataSource)理解未JAVA中的哈希图(HashMap))同时,参数化规范模式提供了一个模型以一定的标准来验证一个数据源。
注:WACT
WACT,WEB应用程序组件工具箱,能够在SourceForge(http://wact.sf.net)上下载到。它是一个PHP库类,用来解决在WEB应用程序开发中一些常用的问题。WACT很注重代码重用、单体测试和使用设计模式方面的技术。WACT理论相关的信息位于http://wact.sf.net/index.php/datasource
WACT数据源(DataSource)类包含在这本书的源代码里面,这样你可以方便的测试这些代码。
在这个例子中,数据源(DataSource)类可以被认为如下面的代码所示,它几乎和第5章开发的Register(注册)类完全一样。
class DataSource {
protected $store = array();
function get($key) {
if (array_key_exists($key, $this->store))
return $this->store[$key];
}
function set($key, $val) {
$this->store[$key] = $val;
}
}
数据源(DataSource)直接通过一串标识符来获取一个对象的属性。方法Set()用来改变原有的属性或者动态的创建新的属性,方法get()则能返回指定名称的属性。
当你的应用程序必须加工处理一个表单,你可以先把$_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 {
protected $field;
protected $regex;
public function __construct($field, $regex) {
$this->field = $field;
$this->regex = $regex;
}
public function isSatisfiedBy($datasource) {
return preg_match($this->regex, $datasource->get($this->field));
}
}
在这个例子里,这个字段对应的值和PCRE表达式都在构造的时候保存好了。然后方法isSatisfiedBy()从传递过来的数据源DataSource获取到这个字段,并且使用preg_match()方法来比较它的值是否满足对应的正则表达式。