当前位置: 主页 > 编程知识 > Php编程 > 全面介绍php设计模式之伪对象模式

全面介绍php设计模式之伪对象模式

时间:2010-1-25来源:站长资讯网 点击:

重构已有程序

下面让我们用伪对象来帮助重构一个已有程序。考虑一个简单的脚本,它可以模拟你在无数的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);

// ...

}

}

站长资讯网
.
分页: [1] [2] [3] [4] [5] [6] [7]
TAG: php 伪对象模式
推荐内容最近更新人气排行
关于我们 | 友情链接 | 网址推荐 | 常用资讯 | 网站地图 | RSS | 留言