谈php设计模式介绍——伪对象模式(3)_PHP教程

编辑Tag赚U币
教程Tag:暂无Tag,欢迎添加,赚取U币!

推荐:解析php字符串处理函数
addcslashes 为字符串里面的部分字符添加反斜线转义字符 addslashes 用指定的方式对字符串里面的字符进行转义 bin2hex 将二进制数据转换成十六进制表示 chr 返回一个字符的ASCII码 chunk_split 按一定的字符长度将字符串分割成小块 convert_cyr_string 将斯

重构已有程序

下面让我们用伪对象来帮助重构一个已有程序。考虑一个简单的脚本,它可以模拟你在无数的PHP程序中所期望的行为:例如一个当检查到你未登录时要求登录的页面;与此类似的还有表单处理页面;它能在成功登录后显示不同内容并提供登出的功能。 让我们写一个这样的页面。首先,对还未登录的用户显示一个登录表单。

<html>

<body>

<form method=”post”>

Name:<input type=”text” name=”name”> Password:<input type=”password” name=”passwd”>

<input type=”submit” value=”Login”>

</form>

</body>

</html>

接着,显示登录成功后的内容:

<html>

<body>Welcome <?php echo $_SESSION[‘name’]; ?>

<br>Super secret member only content here.

<a href=”<?php echo SELF; ?>?clear”>Logout</a>

</body>

</html>

加入表单处理的功能,session(会话)开始,还有登出的功能,整体看起来应该类似这样:

session_start();

define(‘SELF’,

‘http://’.$_SERVER[‘SERVER_NAME’].$_SERVER[‘PHP_SELF’]);

if (array_key_exists(‘name’, $_REQUEST)

&& array_key_exists(‘passwd’, $_REQUEST)

&& ‘admin’ == $_REQUEST[‘name’]

&& ‘secret’ == $_REQUEST[‘passwd’]) {

$_SESSION[‘name’] = ‘admin’;

header(‘Location: ‘.SELF);

}

if (array_key_exists(‘clear’, $_REQUEST)) {

unset($_SESSION[‘name’]);

}

if (array_key_exists(‘name’, $_SESSION)

&& $_SESSION[‘name’]) { ?>

<html>

<body>Welcome <?=$_SESSION[‘name’]?>

<br>Super secret member only content here.

<a href=”<?php echo SELF; ?>?clear”>Logout</a>

</body>

</html> <?php

} else { ?>

<html>

<body>

<form method=”post”>

Name:<input type=”text” name=”name”> Password:<input type=”password” name=”passwd”>

<input type=”submit” value=”Login”>

</form>

</body>

</html> <?php

}

重构这个程序的一个目的应该是使其成为一个“易于测试”的程序。基于这个目的,如果你还选择一些PHP中的方便特性——如超级全局变量——你将失去测试上的简洁性。

例如,如果你直接就用了$_SESSION,即意味着只有一种途径可以测试这个代码,就是改变$_SESSION。如果你忘了将$_SESSION改回先前已知的状态,各种测试间就会互相干扰。

一个好的解决方法是封装$_SESSION到另一个类中,传递所封装类的实例到任何想要访问$_SESSION的对象。如果你创建了一个已封装对象的伪对象用于测试,你能够完全控制对象对所调用方法的响应(就像ServerStub那样)并且你能核实它是如何调用的(那正是创建伪对象的目的)。

具备了这个思想,让我们看看如何封装$_SESSION之类的全局变量。

class Session {

function Session() {

$this->init();

}

function init() {

if (!isset($_SESSION)) {

if (headers_sent()) {

trigger_error(

‘Session not started before creating session object’);

} else {

session_start();

}

}

}
function isValid($key) {
return array_key_exists($key, $_SESSION);
}
function get($key) {

return (array_key_exists($key, $_SESSION))

? $_SESSION[$key]

: null;

}

function set($key, $value) {

$_SESSION[$key] = $value;

}
function clear($key) {

unset($_SESSION[$key]);

}

}

类Session封装了全局变量$_SESSION。对类SESSION的测试非常类似于对前期的已注册的类的改良测试(参见第5章),但是却无任何通过参数获得或设置相应值的意图。

你也许注意到了构造函数调用了Session::init()方法。为什么这个方法不是构造函数的一部分呢?这样分开的好处是你能静态调用它并确保session已经开始。下面是一个如何使用该类的例子。

Session::init();

$page =& new PageDirector(new Session);

大部分测试方面的文献很推崇伪对象并建议你亲自写一个。如果你打算那样做,开始测试时你就只需要充实那些你需要的方法就可以了。譬如,一个用于处理代码的ServerStub的Session类很可能是这样的:

class MyMockSessionUser1 {

function isValid($key) {

return (‘user_id’ == $key) ? true : false;

}

function get($key) {

if (‘user_id’ == $key) {

return 1;

}

}

}

幸运的是,你可以用SimpleTest来避免那些易范的错误。Mock::generate()方法允许你创建一个类来实例化或动态地配置你想要的结果。

注:伪对象技术
SimpleTest所使用的方法仅是伪对象的多种用法之一。伪对象的代码传递是另一种。随着PHP5的到来,你也许能看到伪对象以对象中的__call()方法来执行。

以下是如何用SimpleTest生成的伪对象来测试并重构MyMockSessionUser1类(如上例中)。

Mock::Generate(‘Session’);

class PageDirectorTestCase extends UnitTestCase {

function testSomethingWhichUsesSession() {

$session =& new MockSession($this);

$session->setReturnValue(‘isValid’, true);

$session->setReturnValue(‘get’, 1);

// ...

}

}

分享:怎样把握技巧开发PHP网站
1.使用 ip2long() 和 long2ip() 函数来把 IP 地址转化成整型存储到数据库里。这种方法把存储空间降到了接近四分之一(char(15) 的 15 个字节对整形的 4 个字节),计算一个特定的地址是不是在一个区段内页更简单了,而且加快了搜索和排序的速度(虽然有时仅

来源:模板无忧//所属分类:PHP教程/更新时间:2009-06-20
相关PHP教程