构造开发模板 五种PHP设计模式
设计形式只是为 Java 架构师预备的 —— 至少您能够不断如许以为。实践上,设计形式关于每小我都十分有效。假如这些东西不是 “架构太空人” 的专利,那么它们又是什么?为什么说它们在 PHP 使用顺序中十分有效?本文分析了这些问题。
设计形式 一书将设计形式引入软件社区,该书的作者是 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides Design(俗称 “四人帮”)。所引见的设计形式背面的中心概念十分简略。经由多年的软件开拓理论,Gamma 等人发现了某些具有固定设计的形式,就像修建师设计房子和修建物一样,可认为浴室的地位或厨房的结构方法开拓模板。运用这些模板或许说设计形式 意味着可以更快地设计更好的修建物。相同的概念也合用于软件。
设计形式不只代表着更快开拓强健软件的有效办法,并且还供应了以友爱的术语封装大型理念的办法。例如,您可以说您正在编写一个供应松懈耦合的音讯传递系统,也可以说你正在编写称号为察看者 的形式。
用较小的示例展现形式的价值长短常坚苦的。这往往有些牛鼎烹鸡的意味,由于形式实践上是在大型代码库中发扬效果的。本文不展现大型使用顺序,所以您需求思考的是在您本人的大型使用顺序中使用示例道理的办法 —— 而不是本文演示的代码自身。这不是说您不该该在小使用顺序中运用形式。良多优越的使用顺序都以小使用顺序为起点,逐步开展到大型使用顺序,所以没有来由不以此类扎实的编码理论为根底。 既然您曾经调查了设计形式以及它们的有效之处,目前我们来看看 PHP V5 的五种常用形式。
工场形式
开始在设计形式 一书中,很多设计形式都鼓舞运用松懈耦合。要了解这个概念,让我们最好谈一下很多开拓人员从事大型系统的艰辛过程。在更改一个代码片段时,就会发作问题,系统其他局部 —— 您曾以为完全不相关的局部中也有能够呈现级联毁坏。
该问题在于严密耦合 。系统某个局部中的函数和类严峻依靠于系统的其他局部中函数和类的行为和构造。您需求一组形式,使这些类可以互相通讯,但不但愿将它们严密绑定在一同,以防止呈现联锁。 在大型系统中,很多代码依靠于少量几个要害类。需求更改这些类时,能够会呈现坚苦。例如,假定您有一个从文件读取的 User 类。您但愿将其更改为从数据库读取的其他类,然则,一切的代码都援用从文件读取的原始类。这时分,运用工场形式会很便利。
工场形式 是一品种,它具有为您创立对象的某些办法。您可以运用工场类创立对象,而不直接运用 new。如许,假如您想要更改所创立的对象类型,只需更改该工场即可。运用该工场的一切代码会主动更改。
清单 1 显示工场类的一个示列。等式的效劳器端包罗两个局部:数据库和一组 PHP 页面,这些页面答应您添加反应、恳求反应列表并获取与特定反应相关的文章。
清单 1. Factory1.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 透露表现。
图 1. 工场类及其相关 IUser 接口和用户类
假如您运用 php 分析器在敕令行上运转此代码,将获得如下后果:
Jack
%
测试代码会向工场恳求 User 对象,并输出 getName 办法的后果。
有一种工场形式的变体运用工场办法。类中的这些公共静态办法结构该类型的对象。假如创立此类型的对象十分主要,此办法十分有效。例如,假定您需求先创立对象,然后设置很多属性。此版本的工场形式会将该历程封装在单个地位中,如许,不必复制复杂的初始化代码,也不用将复制好的代码在在代码库中四处粘贴。 清单 2 显示运用工场办法的一个示例。
清单 2. Factory2.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 透露表现。
图 2. IUser 接口和带有工场办法的 user 类
在敕令行中运转剧本发生的后果与清单 1 的后果一样,如下所示:
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 所示。
图 3. 数据库衔接单位素
在两次挪用间,handle 办法返回的数据库句柄是一样的,这就是最好的证实。您可以在敕令行中运转代码来察看这一点。
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 中展现了这些元素。
图 4. 可察看的用户列表和用户列表事情日记顺序
假如在敕令行中运转它,您将看到以下输出:
'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。
图 5. 敕令链及其相关敕令
假如您运转包括某些测试代码的剧本,则会获得以下输出:
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 );
?>
图 6. 用户列表和用于选择用户的战略
UserList 类是打包称号数组的一个包装器。它完成 find 办法,该办法应用几个战略之一来选择这些称号的子集。这些战略由 IStrategy 接口界说,该接口有两个完成:一个随机选择用户,另一个依据指命名称选择这以后的一切称号。运转测试代码时,将获得以下输出:
Array
(
[0] => Jack
[1] => Lori
[2] => Megan
)
Array
(
[0] => Andy
[1] => Megan
)
%
测试代码为两个战略运转统一用户列表,并显示后果。在第一种状况中,战略查找陈列在 J 后的任何称号,所以您将获得 Jack、Lori 和 Megan。第二个战略随机拔取称号,每次会发生分歧的后果。在这种状况下,后果为 Andy 和 Megan。
战略形式十分合适复杂数据治理系统或数据处置系统,二者在数据挑选、查找或处置的方法方面需求较高的灵敏性。
完毕语
本文引见的仅仅是 PHP 使用顺序中运用的几种最经常见的设计形式。在设计形式 一书中演示了更多的设计形式。不要因架构的奥秘性而抛弃。形式是一种绝妙的理念,合用于任何编程言语、任何技艺程度。
- 1网站制作绝对不可以犯的编程错误
- 2评估企业站做的好坏的方法
- 3利用构造方法实现模块的解耦
- 4如何玩转数据库设计
- 5地方生活优惠电子商务网站需求分析
- 6如何让您的网站盈利中发挥到极致
- 7玩具租赁系统功能列表
- 8p2p网贷系统可分为三部分
- 9玩具租赁商城系统需求4
- 10最新动态-久途迁新址
- 11当前电子商务的主流贸易形态
- 12企业建站要写简洁的代码
- 13Asia-Pacific Economic Cooperation 工商咨询理事会亚太中小企业峰会
- 14全站内置SEO优化机制
- 15如何使自己的企业网站和同行业的网站不类似冲突
- 16网站备案所需材料
- 17久途教你怎么样经营自己的网站
- 18二维码是网站建设推广和发展的双刃剑
- 19企业为什么偏爱要专门的网站建设企业做官网呢?
- 20PHP函数代码段
- 21房地产行业微信营销方案3
- 22PhoneGap新手总是需要一些基础问题的解答
- 23如何用PHP模拟QQ登录
- 24企业信息统计系统开发方案
- 25玩具租赁商城系统需求5
- 26阿里云服务器年终六折疯抢
- 27JavaScript cookie详解
- 28上海天煜商业联盟成功上线
- 29Windows Azure 网站上运行 CakePHP
- 30企业为啥要求权威的网站维护单位做官方网站呢?
成都公司:成都市成华区建设南路160号1层9号
重庆公司:重庆市江北区红旗河沟华创商务大厦18楼