设计模式只是为 Java 架构师准备的 —— 至少您可能一直这样认为。实际上,设计模式对于每个人都非常有用。如果这些工具不是 “架构太空人” 的专利,那么它们又是什么?为什么说它们在 PHP 应用程序中非常有用?本文解释了这些问题。
设计模式不仅代表着更快开发健壮软件的有用方法,而且还提供了以友好的术语封装大型理念的方法。例如,您可以说您正在编写一个提供松散耦合的消息传递系统,也可以说你正在编写名称为观察者 的模式。
用较小的示例展示模式的价值是非常困难的。这往往有些大材小用的意味,因为模式实际上是在大型代码库中发挥作用的。本文不展示大型应用程序,所以您需要思索的是在您自己的大型应用程序中应用示例原理的方法——而不是本文演示的代码本身。这不是说您不应该在小应用程序中使用模式。很多良好的应用程序都以小应用程序为起点,逐渐发展到大型应用程序,所以没有理由不以此类扎实的编码实践为基础。
既然您已经了解了设计模式以及它们的有用之处,现在我们来看看 PHP5 的五种常用模式。
工厂模式
最初在设计模式 一书中,许多设计模式都鼓励使用松散耦合。要理解这个概念,让我们最好谈一下许多开发人员从事大型系统的艰苦历程。在更改一个代码片段时,就会发生问题,系统其他部分 —— 您曾认为完全不相关的部分中也有可能出现级联破坏。
该问题在于紧密耦合 。系统某个部分中的函数和类严重依赖于系统的其他部分中函数和类的行为和结构。您需要一组模式,使这些类能够相互通信,但不希望将它们紧密绑定在一起,以避免出现联锁。
在大型系统中,许多代码依赖于少数几个关键类。需要更改这些类时,可能会出现困难。例如,假设您有一个从文件读取的 User 类。您希望将其更改为从数据库读取的其他类,但是,所有的代码都引用从文件读取的原始类。这时候,使用工厂模式会很方便。
工厂模式 是一种类,它具有为您创建对象的某些方法。您可以使用工厂类创建对象,而不直接使用 new。这样,如果您想要更改所创建的对象类型,只需更改该工厂即可。使用该工厂的所有代码会自动更改。
清单 1 显示工厂类的一个示列。等式的服务器端包括两个部分:数据库和一组 PHP 页面,这些页面允许您添加反馈、请求反馈列表并获取与特定反馈相关的文章。
清单 1. Factory1.php
<?php
interfaceIUser
{
functiongetName();
}
classUserimplementsIUser
{
publicfunction__construct($id){}
publicfunctiongetName()
{
return"Jack";
}
}
classUserFactory
{
publicstaticfunctionCreate($id)
{
returnnewUser($id);
}
}
$uo=UserFactory::Create(1);
echo($uo->getName()."/n");
?>
<?php
interfaceIUser
{
functiongetName();
}
classUserimplementsIUser
{
publicstaticfunctionLoad($id)
{
returnnewUser($id);
}
publicstaticfunctionCreate()
{
returnnewUser(null);
}
publicfunction__construct($id){}
publicfunctiongetName()
{
return"Jack";
}
}
$uo=User::Load(1);
echo($uo->getName()."/n");
?>
<?php
require_once("DB.php");
classDatabaseConnection
{
publicstaticfunctionget()
{
static$db=null;
if($db==null)
$db=newDatabaseConnection();
return$db;
}
private$_handle=null;
privatefunction__construct()
{
$dsn='mysql://root:password@localhost/photos';
$this->_handle=&DB::Connect($dsn,array());
}
publicfunctionhandle()
{
return$this->_handle;
}
}
print("Handle=".DatabaseConnection::get()->handle()."/n");
print("Handle=".DatabaseConnection::get()->handle()."/n");
?>
<?php
interfaceIObserver
{
functiononChanged($sender,$args);
}
interfaceIObservable
{
functionaddObserver($observer);
}
classUserListimplementsIObservable
{
private$_observers=array();
publicfunctionaddCustomer($name)
{
foreach($this->_observersas$obs)
$obs->onChanged($this,$name);
}
publicfunctionaddObserver($observer)
{
$this->_observers[]=$observer;
}
}
classUserListLoggerimplementsIObserver
{
publicfunctiononChanged($sender,$args)
{
echo("'$args'addedtouserlist/n");
}
}
$ul=newUserList();
$ul->addObserver(newUserListLogger());
$ul->addCustomer("Jack");
?>
<?php
interfaceICommand
{
functiononCommand($name,$args);
}
classCommandChain
{
private$_commands=array();
publicfunctionaddCommand($cmd)
{
$this->_commands[]=$cmd;
}
publicfunctionrunCommand($name,$args)
{
foreach($this->_commandsas$cmd)
{
if($cmd->onCommand($name,$args))
return;
}
}
}
classUserCommandimplementsICommand
{
publicfunctiononCommand($name,$args)
{
if($name!='addUser')returnfalse;
echo("UserCommandhandling'addUser'/n");
returntrue;
}
}
classMailCommandimplementsICommand
{
publicfunctiononCommand($name,$args)
{
if($name!='mail')returnfalse;
echo("MailCommandhandling'mail'/n");
returntrue;
}
}
$cc=newCommandChain();
$cc->addCommand(newUserCommand());
$cc->addCommand(newMailCommand());
$cc->runCommand('addUser',null);
$cc->runCommand('mail',null);
?>
<?php
interfaceIStrategy
{
functionfilter($record);
}
classFindAfterStrategyimplementsIStrategy
{
private$_name;
publicfunction__construct($name)
{
$this->_name=$name;
}
publicfunctionfilter($record)
{
returnstrcmp($this->_name,$record)<=0;
}
}
classRandomStrategyimplementsIStrategy
{
publicfunctionfilter($record)
{
returnrand(0,1)>=0.5;
}
}
classUserList
{
private$_list=array();
publicfunction__construct($names)
{
if($names!=null)
{
foreach($namesas$name)
{
$this->_list[]=$name;
}
}
}
publicfunctionadd($name)
{
$this->_list[]=$name;
}
publicfunctionfind($filter)
{
$recs=array();
foreach($this->_listas$user)
{
if($filter->filter($user))
$recs[]=$user;
}
return$recs;
}
}
$ul=newUserList(array("Andy","Jack","Lori","Megan"));
$f1=$ul->find(newFindAfterStrategy("J"));
print_r($f1);
$f2=$ul->find(newRandomStrategy());
print_r($f2);
?>