博学而笃志 切问而近思 仁在其中
详情
php设计模式介绍之策略模式
作者:Aliot     发布时间:2017-07-02     评论:0     阅读:0

php设计模式介绍之策略模式

时间:2009-12-30 forest

在编写面向对象的代码的时,有些时候你需要一个能够自己根据不同的条件来引入不同的操作对象实 例。例如,一个菜单功能能够根据用户的“皮肤”首选项来决定是否采用水平的还是垂直的 排列形式,或者一个计费系统可以自行根据用户的收货地址来决定税率。

一般来讲,一个控制菜 单的对象实例包括了add(), delete(), 和 replace()等菜单元素;并通过set()进行配置,用render() 来管理显示模式。无论你想生成什么样子的菜单,你都可以用同一个对象类来处理。不同菜单的对象实 例只是一些方式函数的运算规则不同罢了,至少在刚才的例子里面render()函数是不同的。

但是 如果你需要增加菜单的显示模式种类,或者你需要根据用户的国家、省份等信息来判断菜单排列的顺序 的时候,该怎么做呢?而且如果有许多的方式函数都是经常变化的,那么简单的类封装将变得复杂、难 易理解和升级的。

问题

怎么轻松地改变对象实例的执行过程,因而在代码执行的时候动 态地改变执行过程?一旦实现了这个功能,如果去编写这样的类定义从而让维护和升级变得非常简单呢 ?

解决办法

当一个类封装了多个操作的时候,对象实例可以动态地选择这些操作来进行 ,可以用策略模式来把对象本身和运算规则区分开来。或者,更简单的处理是类里面定义的方式函数用 case语句来进行控制。当然更简单的方法是使用策略模式。

策略模式功能非常强大,因为这个设 计模式本身的核心思想就是面向对象编程的多形性的思想。

就在编程领域之外,有许多例子是关 于策略模式的。如果我需要在清晨从家里去上班,我可以有几个策略可以考虑:我可以开车,乘坐公交 车,走路,汽车或者甚至是搭乘直升飞机。每个策略都可以得到相同的结果,但是它们使用了不同的资 源。选择策略的依据是费用,时间,使用工具还有每种方式的方便程度 。一个很好的策略也许在第二天 就不能再被使用的,所以策略的选择是相对的。

你已经在前面的工厂模式章节看到了和策略模式 相似的例子:因为不同特性的费用计算方式不同,所以Monopoly游戏的框架使用了许多相似的特性类,但 是因为费用的计算不是从类本身获得,所以这个费用计算相对来说是一个TemplateMethod 设计模式。

例子

举例子说明,让我们做一个存储PHP参数的cache。这个cahce类需要把变量以PHP识 别的方式写入到一个文件当中,所以你可以在以后加载该文件并使用它。这个类还应该可以让你为每个 数据加个标识符和存储的方式。

数据缓存

注:缓存是为了在接下来的操作中继续使用而 对资源进行缓存。你可以通过建立和使用缓存来节省直接从原数据库获取数据的时间。这方面的例子最 常见的就是访问数据库或者解析大的XML文档,或者大的配置文件。

缓存也会出现一个问题:你 的缓存可能会失去与原数据的同步。或者缓存需要使用太多内存。

最开始,我们开发一个缓存操 作,并不使用策略模式。

因为你可能需要缓存的不止一个值,所以你需要使用标识符来标识出你 需要指定的元素。在这个例子中,标识符就是’application_config’。下面试一个如果使 用cache的例子。

// PHP4

$config_cache =& new VarCache (‘application_config’);
if ($config_cache->isValid()) {
$config  = $config_cache->get();
} else {
$config =  slow_expensive_function_to_get_config();
$config_cache->set($config);
}

这个代码生成了一个新的VarCache对象存放在$config_cache变量里面。这个数据在缓存 中的标识符是 ‘application_config’。如果在缓存里面有这个数据, isValid() 将返回 真( true )并且获取缓存中的数据。反之,值被重新获取并写入缓存当中,以便下次使用。

按 照一般的需求,让我们开始编写这段代码来进行测试。首先,如果缓存中没有该数据, isValid() 方式 函数应该返回非值(false)。

class VarCacheTestCase extends UnitTestCase {
function TestUnsetValueIsInvalid() {
$cache =& new VarCache (‘foo’);
$this->assertFalse($cache->isValid());
}

因为VarCache现在没有代码,所以最简单的方式就是先构造一个方式函数。

class  VarCache {
function isValid() {}
}

这样,我们就可以继续了。

class VarCacheTestCase extends UnitTestCase {
function  TestUnsetValueIsInvalid() { /* ... */ }
function TestIsValidTrueAfterSet() {
$cache =& new VarCache(‘foo’);
$cache->set (‘bar’);
$this->assertTrue($cache->isValid());
}

上面的测试校验了缓存的数据是否是可用的。

开始编写cache类的主要部分。VarCache 引入一个 标识符, 所以constructor了一个应该记录它的对象实例。这里面还有一个set()的方式函数,用来把 数据存入缓存,或者当数据存在时,修改缓存当中的数据。

class VarCache {
var $_name;
function VarCache($name) {
$this->_name =  ‘cache/’.$name;
}
function isValid() {
return file_exists ($this->_name.’.php’);
}
function set() {
$file_handle =  fopen($this->_name.’.php’, ‘w’);
fclose($file_handle);
}
}


相关文章
loading......
最新动态
所有评论

loading......

网站声明:
本站部分内容来自网络,如您发现本站内容
侵害到您的利益,请联系本站管理员处理。
联系站长
373515719@qq.com
关于本站:
编程参考手册