php教程:php设计模式介绍之观测模式(2)

http://www.itjxue.com  2015-07-17 08:20  来源:未知  点击次数: 

为了实现以观测模式为基础的错误记录句柄,首先我们注意到作为观测者的FileErrorLogger类和EmailErrorLogger类什么也不能做。那么,FileErrorLogger类是如何向一个文件写出错信息,EmailErrorLogger类又如何发送电子邮件的? 接下来,让我来看看用来实现观测模式的技术细节,然后,再集中精力来看看该模式的主体――ErrorHandler的细节。最后,再写一些错误处理函数来调用这个ErrorHandler类。

最后用下面的这一段代码来表示:


//  PHP4
$eh  =&  getErrorHandlerInstance();
$eh->attach(new  EmailErrorLogger(‘jsweat_php@yahoo.com’));
$eh->attach(new  FileErrorLogger(fopen(‘error.log’,’w’)));

set_error_handler(‘observer_error_handler’);

//  ...  later
trigger_error(‘this  is  an  error’);


ErrorHandler类是一种单件模式(参考第4章:The Singleton Pattern)。它可以通过函数Attach()来注册各种错误信息观测者,而set_error_handler()函数就是一个指向ErrorHandler类的函数。最后,当一个错误信息被触发后,所有的观测者都会得到通知。

为了使这次观测的操作生效,你的测试必须能证明所有的这些操作(将错误信息写入日志,利用电子邮件发送错误信息)都能得到执行,并且能正常工作。简而言之,让我们来看看一系列简单的测试。(和这个实例有关的其他更多实例,可以在本书附带的源代码中找到)

这里有FileErrorLogger类联合测试的一部分代码:它用来测试当FileErrorlogger类被某个对象实例化时,是否具有向一个文件写日志的能力。


class  FileErrorLoggerTestCase  extends  UnitTestCase  {
var  $_fh;
var  $_test_file  =  ‘test.log’;

function  setup()  {
@unlink($this->_test_file);
$this->_fh  =  fopen($this->_test_file,  ‘w’);
}

function  TestRequiresFileHandleToInstantiate()  {  /*  ...  */  }

function  TestWrite()  {
$content  =  ‘test’.rand(10,100);
$log  =&  new  FileErrorLogger($this->_fh);

$log->write($content);
$file_contents  =  file_get_contents($this->_test_file);
$this->assertWantedPattern(‘/’.$content.’$/’,  $file_contents);
}

function  TestWriteIsTimeStamped()  {  /*  ...  */  }

}

在这个测试中, setup()函数创建了一个文件指针,指向一个名为“test.log”的新文件。并且,将该指针保存在变量$_fh中,这个可写的文件指针将作为一个变量传递给FileErrorlogger对象的实例,进行测试。变量$content的值将传递给函数write(),并且,在存储结束后,还将用来被检查$content的值是否确实被正确写入test.log文件中。

(这个测试要求PHP必须具有向那个新建的test.log中写数据的权限。)

下面的一些代码也许可以帮助FileErrorLogger类通过测试。

class  FileErrorLogger  {
var  $_fh;
function  FileErrorLogger($file_handle)  {
$this->_fh  =  $file_handle;
}
function  write($msg)  {
fwrite($this->_fh,  date(‘Y-m-d  H:i:s:  ‘).$msg);
}
}

一个类似的测试代码可以使EmailErrorLogger类生效。


class  EmailErrorLoggerTestCase  extends  UnitTestCase  {
function  TestEmailAddressFirstConstructorParameter()  {
$log  =&  new  EmailErrorLogger;
$this->assertErrorPattern(‘/missing.*1/i’);
}

function  TestMail()  {
$log  =&  new  EmailErrorLogger(‘jsweat_php@yahoo.com’);
$log->mail(‘test  message’);
}
}

接下来,通过这个测试的EmailErrorLogger类的代码如下:


class  EmailErrorLogger  {
var  $_addr;
var  $_subject;

function  EmailErrorLogger($addr,
$subject=’Application  Error  Message’)  {
$this->_addr  =  $addr;
$this->_subject  =  $subject;
}

function  mail($msg)  {
mail($this->_addr
,$this->_subject
,date(‘Y-m-d  H:i:s:  ‘).$msg);
}
}

你是怎样确定EmailErrorLogger类能真正发送电子邮件的呢?是的,你可以打开你的收件箱,看看其中是否有新邮件,就知道了。但是,那就不是一个全自动的测试了。 或者说,这个测试就只是伪模式的一个不错的替代方案。(至于如何创建一个控制邮件的类,将作为一个练习留给读者的。详细信息,请参考第6章The MockObject Pattern 或参考FakeMail项目http://sf.net/projects/fakemail/.)

(责任编辑:IT教学网)

更多