PHP网页编程之五种罕见的PHP设计形式
参加PHP开发学习,或许只是一次偶然的想法吧!只是想在走向社会之前体验、学习在一个公司或者说是项目团队之中如何去更有效的沟通、交流、共同合作,还有就是为毕业实习找工作增加伐码。设计 设计形式只是为 Java 架构师筹办的 ―― 最少您能够一向如许以为。实践上,设计形式关于每一个人都十分有效。假如这些东西不是 “架构太空人” 的专利,那末它们又是甚么?为何说它们在 使用法式中十分有效?本文注释了这些成绩。PHP设计形式 一书将设计形式引入软件社区,该书的作者是 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides Design(俗称 “四人帮”)。所引见的设计形式面前的中心概念十分复杂。经由多年的软件开辟理论,Gamma 等人发明了某些具有固定设计的形式,就像修建师设计房子和修建物一样,可觉得浴室的地位或厨房的机关体例开辟模板。利用这些模板或说设计形式 意味着可以更快地设计更好的修建物。一样的概念也合用于软件。
设计形式不但代表着更快开辟强健软件的有效办法,并且还供应了以友爱的术语封装大型理念的办法。例如,您可以说您正在编写一个供应松懈耦合的动静传递体系,也能够说你正在编写称号为察看者 的形式。
用较小的示例展现形式的价值长短常坚苦的。这常常有些牛鼎烹鸡的意味,由于形式实践上是在大型代码库中发扬感化的。本文不展现大型使用法式,所以您需求思考的是在您本人的大型使用法式中使用示例道理的办法 ―― 而不是本文演示的代码自己。这不是说您不该该在小使用法式中利用形式。良多优秀的使用法式都以小使用法式为出发点,逐步开展到大型使用法式,所以没有来由不以此类扎实的编码理论为基本。
既然您已懂得了设计形式和它们的有效的地方,如今咱们来看看 PHP V5 的五种经常使用形式。
工场形式
最后在设计形式 一书中,很多设计形式都勉励利用松懈耦合。要了解这个概念,让咱们最好谈一下很多开辟人员从事大型体系的艰辛过程。在更改一个代码片断时,就会产生成绩,体系其他局部 ―― 您曾以为完整不相干的局部中也有能够呈现级联损坏。
该成绩在于严密耦合 。体系某个局部中的函数和类严重依附于体系的其他局部中函数和类的行动和布局。您需求一组形式,使这些类可以互相通讯,但不但愿将它们严密绑定在一同,以免呈现联锁。
在大型体系中,很多代码依附于多数几个关头类。需求更改这些类时,能够会呈现坚苦。例如,假定您有一个从文件读取的 User 类。您但愿将其更改成从数据库读取的其他类,然而,一切的代码都援用从文件读取的原始类。这时候候,利用工场形式会很便利。
工场形式 是一品种,它具无为您创立对象的某些办法。您可使用工场类创立对象,而不直接利用 new。如许,假如您想要更改所创立的对象类型,只需更改该工场便可。利用该工场的一切代码会主动更改。
清单 1 显示工场类的一个示列。等式的办事器端包含两个局部:数据库和一组 PHP 页面,这些页面答应您添加反应、恳求反应列表并获得与特定反应相干的文章。
清单 1. Factory1.php
<?php
interface IUser
{
function getName();
}
class User implements IUser
{
public function __construct( $id ) { }
public function getName()
{
return "Jack";
}
}
class UserFactory
{
public static function Create( $id )
{
return new User( $id );
}
}
$uo = UserFactory::Create( 1 );
echo( $uo->getName()."\n" );
?>
IUser 接口界说用户对象应履行甚么操作。IUser 的完成称为 User,UserFactory 工场类则创立 IUser 对象。此关系可以用图 1 中的 UML 暗示。
http://www.pushad.com/XrssFile/2007-1/25/2007125101243810.jpg
图 1. 工场类及其相干 IUser 接口和用户类
假如您利用 php 注释器在号令行上运转此代码,将失掉以下了局:
% php factory1.php
Jack
%
测试代码会向工场恳求 User 对象,并输入 getName 办法的了局。
有一种工场形式的变体利用工场办法。类中的这些公共静态办法机关该类型的对象。假如创立此类型的对象十分主要,此办法十分有效。例如,假定您需求先创立对象,然后设置很多属性。此版本的工场形式会将该历程封装在单个地位中,如许,不必复制庞杂的初始化代码,也不用将复制好的代码在在代码库中各处粘贴。
清单 2 显示利用工场办法的一个示例。
清单 2. Factory2.php
<?php
interface IUser
{
function getName();
}
class User implements IUser
{
public static function Load( $id )
{
return new User( $id );
}
public static function Create( )
{
return new User( null );
}
public function __construct( $id ) { }
public function getName()
{
return "Jack";
}
}
$uo = User::Load( 1 );
echo( $uo->getName()."\n" );
?>
这段代码要复杂很多。它唯一一个接口 IUser 和一个完成此接口的 User 类。User 类有两个创立对象的静态办法。此关系可用图 2 中的 UML 暗示。
http://www.pushad.com/XrssFile/2007-1/25/2007125101243733.jpg
图 2. IUser 接口和带有工场办法的 user 类
在号令行中运转剧本发生的了局与清单 1 的了局不异,以下所示:
% php factory2.php
Jack
%
如上所述,有时此类形式在范围较小的情况中仿佛有些牛鼎烹鸡。不外,最好仍是进修这类扎实的编码模式,以便使用于恣意范围的项目中。
单位素形式
某些使用法式资本是独有的,由于有且只要一个此类型的资本。例如,经由过程数据库句柄到数据库的毗连是独有的。您但愿在使用法式中同享数据库句柄,由于在坚持毗连翻开或封闭时,它是一种开支,在获得单个页面的过程当中更是如斯。
单位素形式可以知足此请求。假如使用法式每次包括且仅包括一个对象,那末这个对象就是一个单位素(Singleton)。清单 3 中的代码显示了 PHP V5 中的一个数据库毗连单位素。
清单 3. Singleton.php
<?php
require_once("DB.php");
class DatabaseConnection
{
public static function get()
{
static $db = null;
if ( $db == null )
$db = new DatabaseConnection();
return $db;
}
private $_handle = null;
private function __construct()
{
$dsn = 'mysql://root:password@localhost/photos';
$this->_handle =& DB::Connect( $dsn, array() );
}
public function handle()
{
return $this->_handle;
}
}
print( "Handle = ".DatabaseConnection::get()->handle()."\n" );
print( "Handle = ".DatabaseConnection::get()->handle()."\n" );
?>
此代码显示名为 DatabaseConnection 的单个类。您不克不及创立自已的 DatabaseConnection,由于机关函数是公用的。但利用静态 get 办法,您可以取得且仅取得一个 DatabaseConnection 对象。此代码的 UML 如图 3 所示。
http://www.pushad.com/XrssFile/2007-1/25/2007125101243308.jpg
图 3. 数据库毗连单位素
在两次挪用间,handle 办法前往的数据库句柄是不异的,这就是最好的证实。您可以在号令行中运转代码来察看这一点。
% php singleton.php
Handle = Object id #3
Handle = Object id #3
%
前往的两个句柄是统一对象。假如您在全部使用法式中利用数据库毗连单位素,那末就能够在任何中央重用统一句柄。
您可使用全局变量存储数据库句柄,然而,该办法仅合用于较小的使用法式。在较大的使用法式中,应防止利用全局变量,并利用对象和办法会见资本。
察看者形式
察看者形式为您供应了防止组件之间严密耦合的另外一种办法。该形式十分复杂:一个对象经由过程添加一个办法(该办法答应另外一个对象,即察看者 注册本人)使自己变得可察看。当可察看的对象更改时,它会将动静发送到已注册的察看者。这些察看者利用该信息履行的操作与可察看的对象有关。了局是对象可以互相对话,而不用懂得缘由。
一个复杂示例是体系中的用户列表。清单 4 中的代码显示一个用户列表,添加用户时,它将发送出一条动静。添加用户时,经由过程发送动静的日记察看者可以察看此列表。
清单 4. Observer.php
<?php
interface IObserver
{
function onChanged( $sender, $args );
}
interface IObservable
{
function addObserver( $observer );
}
class UserList implements IObservable
{
private $_observers = array();
public function addCustomer( $name )
{
foreach( $this->_observers as $obs )
$obs->onChanged( $this, $name );
}
public function addObserver( $observer )
{
$this->_observers []= $observer;
}
}
class UserListLogger implements IObserver
{
public function onChanged( $sender, $args )
{
echo( "'$args' added to user list\n" );
}
}
$ul = new UserList();
$ul->addObserver( new UserListLogger() );
$ul->addCustomer( "Jack" );
?>
此代码界说四个元素:两个接口和两个类。IObservable 接口界说可以被察看的对象,UserList 完成该接口,以便将自己注册为可察看。IObserver 列表界说要经由过程如何的办法才干成为察看者,UserListLogger 完成 IObserver 接口。图 4 的 UML 中展现了这些元素。
http://www.pushad.com/XrssFile/2007-1/25/2007125101243308.jpg
图 4. 可察看的用户列表和用户列表事务日记法式
假如在号令行中运转它,您将看到以下输入:
% php observer.php
'Jack' added to user list
%
测试代码创立 UserList,并将 UserListLogger 察看者添加到个中。然后添加一个花费者,并将这一更改告诉 UserListLogger。
熟悉到 UserList 不晓得日记法式将履行甚么操作很关头。能够存在一个或多个履行其他操作的侦听法式。例如,您能够有一个向新用户发送动静的察看者,接待新用户利用该体系。这类办法的价值在于 UserList 疏忽一切依附它的对象,它次要存眷在列表更改时保护用户列表并发送动静这一任务。
此形式不限于内存中的对象。它是在较大的使用法式中利用的数据库驱动的动静查询体系的基本。
号令链形式
号令链 形式以松懈耦合主题为基本,发送动静、号令和恳求,或经由过程一组处置法式发送恣意内容。每一个处置法式城市自行判别本人可否处置恳求。假如可以,该恳求被处置,历程中断。您可觉得体系添加或移除处置法式,而不影响其他处置法式。清单 5 显示了此形式的一个示例。
清单 5. Chain.php
<?php
interface ICommand
{
function onCommand( $name, $args );
}
class CommandChain
{
private $_commands = array();
public function addCommand( $cmd )
{
$this->_commands []= $cmd;
}
public function runCommand( $name, $args )
{
foreach( $this->_commands as $cmd )
{
if ( $cmd->onCommand( $name, $args ) )
return;
}
}
}
class UserCommand implements ICommand
{
public function onCommand( $name, $args )
{
if ( $name != 'addUser' ) return false;
echo( "UserCommand handling 'addUser'\n" );
return true;
}
}
class MailCommand implements ICommand
{
public function onCommand( $name, $args )
{
if ( $name != 'mail' ) return false;
echo( "MailCommand handling 'mail'\n" );
return true;
}
}
$cc = new CommandChain();
$cc->addCommand( new UserCommand() );
$cc->addCommand( new MailCommand() );
$cc->runCommand( 'addUser', null );
$cc->runCommand( 'mail', null );
?>
此代码界说保护 ICommand 对象列表的 CommandChain 类。两个类都可以完成 ICommand 接口 ―― 一个对邮件的恳求作出呼应,另外一个对添加用户作出呼应。 图 5 给出了 UML。
http://www.pushad.com/XrssFile/2007-1/25/2007125101244119.jpg
图 5. 号令链及其相干号令
假如您运转包括某些测试代码的剧本,则会失掉以下输入:
% php chain.php
UserCommand handling 'addUser'
MailCommand handling 'mail'
%
代码起首创立 CommandChain 对象,并为它添加两个号令对象的实例。然后运转两个号令以检查谁对这些号令作出了呼应。假如号令的称号婚配 UserCommand 或 MailCommand,则代码掉败,不产生任何操作。
为处置恳求而创立可扩大的架构时,号令链形式很有价值,利用它可以处理很多成绩。
战略形式
咱们讲述的最初一个设计形式是战略 形式。在此形式中,算法是从庞杂类提取的,因此可以便利地交换。例如,假如要更改搜刮引擎中分列页的办法,则战略形式是一个不错的选择。思虑一下搜刮引擎的几个局部 ―― 一局部遍历页面,一局部对每页分列,另外一局部基于分列的了局排序。在庞杂的示例中,这些局部都在统一个类中。经由过程利用战略形式,您可将分列局部放入另外一个类中,以便更改页分列的体例,而不影响搜刮引擎的其他代码。
作为一个较复杂的示例,清单 6 显示了一个用户列表类,它供应了一个依据一组即插即用的战略查找一组用户的办法。
清单 6. Strategy.php
<?php
interface IStrategy
{
function filter( $record );
}
class FindAfterStrategy implements IStrategy
{
private $_name;
public function __construct( $name )
{
$this->_name = $name;
}
public function filter( $record )
{
return strcmp( $this->_name, $record ) <= 0;
}
}
class RandomStrategy implements IStrategy
{
public function filter( $record )
{
return rand( 0, 1 ) >= 0.5;
}
}
class UserList
{
private $_list = array();
public function __construct( $names )
{
if ( $names != null )
{
foreach( $names as $name )
{
$this->_list []= $name;
}
}
}
public function add( $name )
{
$this->_list []= $name;
}
public function find( $filter )
{
$recs = array();
foreach( $this->_list as $user )
{
if ( $filter->filter( $user ) )
$recs []= $user;
}
return $recs;
}
}
$ul = new UserList( array( "Andy", "Jack", "Lori", "Megan" ) );
$f1 = $ul->find( new FindAfterStrategy( "J" ) );
print_r( $f1 );
$f2 = $ul->find( new RandomStrategy() );
print_r( $f2 );
?>
http://www.pushad.com/XrssFile/2007-1/25/2007125101244173.jpg
图 6. 用户列表和用于选择用户的战略
UserList 类是打包称号数组的一个包装器。它完成 find 办法,该办法使用几个战略之一来选择这些称号的子集。这些战略由 IStrategy 接口界说,该接口有两个完成:一个随机选择用户,另外一个依据指命名称选择厥后的一切称号。运转测试代码时,将失掉以下输入:
% php strategy.php
Array
(
=> Jack
=> Lori
=> Megan
)
Array
(
=> Andy
=> Megan
)
%
测试代码为两个战略运转统一用户列表,并显示了局。在第一种情形中,战略查找分列在 J 后的任何称号,所以您将失掉 Jack、Lori 和 Megan。第二个战略随机拔取称号,每次会发生分歧的了局。在这类情形下,了局为 Andy 和 Megan。
战略形式十分合适庞杂数据办理体系或数据处置体系,两者在数据挑选、搜刮或处置的体例方面需求较高的天真性。
停止语
本文引见的仅仅是 PHP 使用法式中利用的几种最多见的设计形式。在设计形式 一书中演示了更多的设计形式。不要因架构的奥秘性而保持。形式是一种绝妙的理念,合用于任何编程言语、任何妙技程度。
不过还好,PHP语言给出的语法错误很详细,只要稍微熟悉一点之后,看错误提示就能很容易找出错误所在的。PHP还有一个特别好用的调试功能,在PHP语句中,你可以随时用echo来输出结果。 其实没啥难的,多练习,练习写程序,真正的实践比看100遍都有用。不过要熟悉引擎 如果你可以写完像留言板这样的程序,那么你可以去一些别人的代码了, 在学习的过程中不能怕麻烦,不能有懒惰的思想。学习php首先应该搭建一个lamp环境或者是wamp环境。这是学习php开发的根本。虽然网络上有很多集成的环境,安装很方便,使用起来也很稳定、 在我安装pear包的时候老是提示,缺少某某文件,才发现 那群extension 的排列是应该有一点的顺序,而我安装的版本的排序不是正常的排序。没办法我只好把那群冒号加了上去,只留下我需要使用的扩展。 最后介绍一个代码出错,但是老找不到错误方法,就是 go to wc (囧),出去换换气没准回来就找到错误啦。 写js我最烦的就是 ie 和 firefox下同样的代码 结果显示的结果千差万别,还是就是最好不要用遨游去调试,因为有时候遨游是禁用js的,有可能代码是争取结果被遨游折腾的认为是代码写错。 再就是混迹于论坛啦,咱们的phpchina的论坛就很强大,提出的问题一般都是有达人去解答的,以前的帖子也要多看看也能学到不少前辈们的经验。别的不错的论坛例如php100,javaeye也是很不错的。 有位前辈曾经跟我说过,phper 至少要掌握200个函数 编起程序来才能顺畅点,那些不熟悉的函数记不住也要一拿手册就能找到。所以建议新手们没事就看看php的手册(至少array函数和string函数是要记牢的)。 这些都是最基本最常用功能,我们这些菜鸟在系统学习后,可以先对这些功能深入研究。 当然这种网站的会员费就几十块钱。 当然这种网站的会员费就几十块钱。 再就是混迹于论坛啦,咱们的phpchina的论坛就很强大,提出的问题一般都是有达人去解答的,以前的帖子也要多看看也能学到不少前辈们的经验。别的不错的论坛例如php100,javaeye也是很不错的。 建议加几个专业的phper的群,当然啦需要说话的人多,一处一点问题能有人回答你的,当然啦要让人回答你的问题,平时就得躲在里面聊天,大家混熟啦,愿意回答你问题的人自然就多啦。 多看优秀程序员编写的代码,仔细理解他们解决问题的方法,对自身有很大的帮助。 本人接触php时间不长,算是phper中的小菜鸟一只吧。由于刚开始学的时候没有名师指,碰过不少疙瘩,呗很多小问题卡过很久,白白浪费不少宝贵的时间,在次分享一些子的学习的心得。 建数据库表的时候,int型要输入长度的,其实是个摆设的输入几位都没影响的,只要大于4就行,囧。 兴趣是最好的老师,百度是最好的词典。 这些中手常用的知识,当你把我说的这些关键字都可以熟练运用的时候,你可以选择自己 本人接触php时间不长,算是phper中的小菜鸟一只吧。由于刚开始学的时候没有名师指,碰过不少疙瘩,呗很多小问题卡过很久,白白浪费不少宝贵的时间,在次分享一些子的学习的心得。
页:
[1]