heiyeluren的blog(黑夜路人的开源世界)

【PHP技术论坛:PHPCup.cn - 中国新锐PHP&LAMP技术论坛】

谢华亮ID:heiyeshuwu
[修改头像]
750899次访问,排名37好友16人,关注者35
既然决定远行,便只顾风雨兼程。
heiyeshuwu的文章
原创 270 篇
翻译 3 篇
转载 193 篇
评论 419 篇
heiyeluren的公告

联系方式:


访问统计: free hit counter code
FeedSky订阅:
FeedSky订阅
最近评论
普拉多:普拉多 Praado: http://praado.vicp.net 专业的网页收藏夹

每天我们上网都会碰到一些有用的、值得珍藏的网页链接地址(简称:网址),于是我们都用浏览器里的收藏夹来收藏。但是现在的电脑病毒相当的猖獗,电脑遭病毒之后,浏览器里收藏的网址几乎就是无法挽救,损失巨大!同时,现在的浏览器市场有多种多样的浏览器,在一台电脑上的浏览器里收藏了某一网址,可是到……
wushenjun:bfdkljgsjgfjkbjkfjugopreigopixfdg
heiyeluren:to: 三马
俺不知道耶,呵呵,咔咔,也许是csdn的rss刷新的不及时。。。
三马:symfony 的配置文件本身就是生成在cache里面的,读取以后才能运行,当然是无法关闭的。在dev的环境下缓存每次都会生成的,也不影响调试,不需要 symfony cc。

路人,你的blog为什么在我的google reader里面没法显示新文章?别人有没有这个问题?
SICTXK:PHP 的 OO 的确是一大进步!
订阅我的博客
XML聚合  FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
订阅到BlogLines
订阅到Yahoo
订阅到GouGou
订阅到飞鸽
订阅到Rojo
订阅到newsgator
订阅到netvibes
文章分类
收藏
    相册
    技术图片
    搜索引擎
    ::eYou::
    kevin world
    lewis - 老吕
    qyb - BT的花
    Realzay的blog
    叶金荣
    天堂地狱鬼-dulao5's Blog
    沙漠之周
    狐狸糊涂
    老韩
    與子觀化
    ::Yahoo::
    glemir’s blog
    Rainx
    stauren
    互联网,请记住我 - 162同学的技术博客
    小蚂蚁同学滴测试博客
    张彪同学
    随网之舞 - kaven的DHTML博客
    ::朋友::
    【推荐】中文分类网
    kevin world
    miky
    俺兄弟的blog
    晋陵路人的Blog
    李天华同学滴技术博客
    沙狐部落
    ::网友::
    Code & Stock.
    LionD8的Blog
    Phzzy
    张贺同学的博客
    技术大牛老余的博客
    抚琴居
    邢红瑞的blog
    阿健的博客
    :PHP博客:
    .: Easy style :.
    [琴剑楼]
    CoolCode.cn
    Haohappy的Blog
    Hightman
    iwind的blog
    Javascript开发站
    JD Space
    Nio's Weblog
    Open Source PHP
    PHP面对对象
    SourceForge.net
    trip的专栏
    UGIA.cn
    windix's blog
    Windix's Weblog
    一个藏袍
    俊麟 Michael`s blog
    偶然的blog
    刘敏的blog
    大龄青年的Blog
    廖宇雷的blog
    懒猫开始新生活blog
    某人的栖息地
    王春生的博客
    神仙
    :牛人blog:
    DBA notes
    侯捷网站
    孟岩
    搜索引擎研究
    方舟
    王咏刚的BLOG
    竹笋炒肉
    荣耀
    车东[Blog^2]
    透明思考
    陈硕的Blog
    DHTML
    DHTMLGoodies
    FCKEditor
    Google Code
    Google Web Toolkit
    HTML Goodies
    HTML.it
    HTMLAre
    HTMLdog
    JavaScript Kit
    jQuery
    KindEditor
    Prototype
    TinyMCE
    W3 Schools
    Yahoo JavaScript Developer Center
    Yahoo! Developer Network
    Yahoo! UI Library (YUI)
    网页设计师Web标准
    Java国内站
    ChinaJavaWorld.com技术论坛
    IBM developerWorks 中国: Java
    Java中文站
    Java开源大全
    Java爱好者
    JR - Java翻译站
    J道-JDON
    Matrix: 与Java共舞
    中国Java开发网
    中文java技术网
    PHP国内站点
    CSDN PHP论坛
    Discuz!
    FleaPHP
    Google--PHP用户组
    IBM DeveloperWorks
    JavsScript技术讨论
    Nirvana Studio
    OpenPHP.cn
    PHPChina
    TiM Club
    中文 PFC 1.0 手册--PHP5的开发包
    中文 PFC 1.0 手册--PHP5的开发包
    中文PHP网
    太平洋--PHP开发区
    爱MySQL
    超越PHP
    PHP国外站点
    ADOdb
    Agavi Framework
    Cake PHP
    MySQL Performance Blog
    MySQL Performance Blog
    Nonaweb
    PEAR
    PECL
    PECL Windows
    PHP Builder
    PHP Classes
    PHP Classes
    PHP New Download
    PHP Security Consortium
    php.MVC
    php.MVC
    PHPkitchen(OO & MVC)
    phpPatterns
    PHP国外图书下载
    smart template
    Smarty
    SourceForge.net
    Symfony Framework
    Zend
    Zend Framework
    Unix C/C++
    Free Gentux
    周立发的blog(Linux C)
    Unix/Linux
    BSD智库
    ChinaUnix
    FreeBSDChina
    FreeLAMP
    IBM开发者Linux专区
    Linux Byte
    LinuxKit
    LinuxTS
    Linux伊甸园
    Linux技术中坚站
    Linux非常空间
    Love Unix
    NetBSD&OpenBSD中文用户组
    NetBSD中国社区
    Oracle中国用户讨论组
    OurLinux
    Unix中文
    Unix中文
    Unix中文宝库
    中国Linux公社
    中国Unix用户技术论坛
    中文FreeBSD用户组
    永远的Unix
    炎黄角马
    程序设计
    CSDN
    IBM开发者中心
    Microsoft TechNet: 主页
    MSDN 中文网站
    PHP中文站
    Sun技术社区
    中国IT认证实验室--企业应用技术
    中国协议分析网
    喜悦国际村
    太平洋电脑网---开发特区
    实用网站
    veBook(国外大量免费图书下载网站)
    Whois.net
    中国Web信息博物馆
    中国互联网络信息中心whois查询
    服务器系统信息查看
    网络安全
    AnySide.com
    CGI Secutiry
    K-OTik Security Monitoring
    Linux Security
    Packet Storm Security
    PHP Secure
    RFC中文文档索引
    Safemode.org
    SecuriTeam.com
    Security Corporation
    SecurityFocus
    SecurityTracker
    Zone-h (区域黑客,每天公布各国被黑的网站)
    中华安全网
    中国信息安全组织
    国家计算机网络应急处理中心
    安全天使
    安全焦点
    幻影旅团
    绿盟科技
    网络安全评估中心(cnns )
    在线手册
    Apache2.0中文文档
    Beyond Linux From Scratch
    Debian参考手册
    FreeBSD Porter 手册
    FreeBSD使用手册
    Linux C函数中文参考手册
    MySQL 4.1.0 中文参考手册
    NetBSD在线手册
    OpenBSD在线FAQ
    PHP ADODB 1.99版手册中文翻译(Tripc)
    PHP中文手册(国内)
    PHP中文手册(国外)
    PostgreSQL中文文档
    Red Hat Linux 9入门指南
    Red Hat Linux 9安装指南
    Red Hat Linux 9定制手册
    中国OSS技术手册中心
    技术文档手册中心-ChinaUnix
    存档

    转载 另外五个 PHP 设计模式

    新一篇: [原创]国外主流PHP框架比较

     

    另外五个 PHP 设计模式

    级别: 中级

    Nathan A. Good (mail@nathanagood.com), 高级信息工程师, 顾问

    2008 年 4 月 28 日

    PHP V5 的面向对象特性使您能够实现设计模式来改进代码设计。通过这种方式改进代码设计,代码在进行修改时将变得更加易读、更易维护且更加健壮。

    设计模式 一书介绍了很多此类概念。当时,我还在学习面向对象 (OO),因此我发现那本书中有许多概念都很难领会。但是,随着越来越熟悉 OO 概念 —— 尤其是接口和继承的使用 —— 我开始看到设计模式中的实际价值。作为一名应用程序开发人员,即使从不了解任何模式或者如何及何时使用这些模式,对您的职业生涯也没有什么大的影响。但是,我发现了解这些模式以及 developerWorks 文章 “五种常见 PHP 设计模式” 中介绍的那些模式的优秀知识后(请参阅 参考资料),您可以完成两件事情:

    启用高带宽会话
    如果了解设计模式,您将能够更快地构建可靠的 OO 应用程序。但当整个开发团队知道各种模式时,您可以突然拥有非常高的带宽会话。您不再需要讨论将到处使用的所有类。相反,您可以与其他人谈论模式。“我要在这里引用一个单例(singleton),然后使用迭代器遍历对象集合,然后……” 比遍历构成这些模式的类、方法和接口快很多。单是通信效率一项就值得花时间以团队的形式通过会话来研究模式。
    减少痛苦的教训
    每个设计模式都描述了一种经过验证的解决常见问题的方法。因此,您无需担心设计是不是正确的,只要您已经选择了提供所需优点的模式。

    缺陷

    有句谚语说得好:“当您手中拿着一把锤子时,所有事物看上去都像钉子”。当您认为自己找到一个优秀模式时,您可能会尝试到处使用它,即使在不应当使用它的位置。记住您必须考虑正在学习的模式的使用目的,不要为了使用模式而把这些模式强行应用到应用程序的各个部分中。

    本文将介绍可用于改进 PHP 代码的五个模式。每个模式都将介绍一个特定场景。可以在 下载 部分中获得这些模式的 PHP 代码。

    要求

    要发挥本文的最大功效并使用示例,需要在计算机中安装以下软件:

    • PHP V5 或更高版本(本文是使用 PHP V5.2.4 撰写的)
    • 压缩程序,例如 WinZIP(用于压缩可下载的代码归档)

    注:虽然您也可以使用纯文本编辑器,但是我发现拥有语法高亮显示和语法纠错功能的编辑器真的很有帮助。本文中的示例是使用 Eclipse PHP Development Tools (PDT) 编写的。





    回页首


    适配器模式

    在需要将一类对象转换成另一类对象时,请使用适配器模式。通常,开发人员通过一系列赋值代码来处理此过程,如清单 1 所示。适配器模式是整理此类代码并在其他位置重用所有赋值代码的优秀方法。此外,它还将隐藏赋值代码,如果同时还要设定格式,这样可以极大地简化工作。


    清单 1. 使用代码在对象之间赋值

                    
    class AddressDisplay
    {
        private $addressType;
        private $addressText;
    
        public function setAddressType($addressType)
        {
            $this->addressType = $addressType;
        }
    
        public function getAddressType()
        {
            return $this->addressType;
        }
    
        public function setAddressText($addressText)
        {
            $this->addressText = $addressText;
        }
    
        public function getAddressText()
        {
            return $this->addressText;
        }
    }
    
    class EmailAddress
    {
        private $emailAddress;
        
        public function getEmailAddress()
        {
            return $this->emailAddress;
        }
        
        public function setEmailAddress($address)
        {
            $this->emailAddress = $address;
        }
    }
    
    $emailAddress = new EmailAddress();
    /* Populate the EmailAddress object */
    $address = new AddressDisplay();
    /* Here's the assignment code, where I'm assigning values 
      from one object to another... */
    $address->setAddressType("email");
    $address->setAddressText($emailAddress->getEmailAddress());
    

    此示例将使用 AddressDisplay 对象把地址显示给用户。AddressDisplay 对象有两部分:地址类型和一个格式化的地址字符串。

    在实现模式(参见清单 2)后,PHP 脚本将不再需要担心如何把 EmailAddress 对象转换成 AddressDisplay 对象。那是件好事,尤其是在 AddressDisplay 对象发生更改时或者控制如何把 EmailAddress 对象转换成 AddressDisplay 对象的规则发生更改时。记住,以模块化风格设计代码的主要优点之一就是,在业务领域发生一些更改时或者需要向软件中添加新功能时尽可能少的使用更改。即使在执行普通任务(例如把一个对象的属性值赋给另一个对象)时,也请考虑使用此模式。


    清单 2. 使用适配器模式

                    
    class EmailAddressDisplayAdapter extends AddressDisplay
    {
        public function __construct($emailAddr)
        {
            $this->setAddressType("email");
            $this->setAddressText($emailAddr->getEmailAddress());
        }
    }	
    
    $email = new EmailAddress();
    $email->setEmailAddress("user@example.com");
    
    $address = new EmailAddressDisplayAdapter($email);
    
    echo($address->getAddressType() . "\n") ;
    echo($address->getAddressText());
    

    图 1 显示了适配器模式的类图。


    图 1. 适配器模式的类图
    适配器模式的类图

    替代方法

    编写适配器的替代方法 —— 并且是推荐方法 —— 是实现一个接口来修改行为,而不是扩展对象。这是一种非常干净的、创建适配器的方法并且没有扩展对象的缺点。使用接口的缺点之一是需要把实现添加到适配器类中,如图 2 所示:


    图 2. 适配器模式(使用接口)
    适配器模式(使用接口)





    回页首


    迭代器模式

    迭代器模式将提供一种通过对象集合或对象数组封装迭代的方法。如果需要遍历集合中不同类型的对象,则使用这种模式尤为便利。

    查看上面清单 1 中的电子邮件和物理地址示例。在添加迭代器模式之前,如果要遍历个人地址,则可能要遍历物理地址并显示这些地址,然后遍历个人电子邮件地址并显示这些地址,然后遍历个人 IM 地址并显示这些地址。非常复杂的遍历!

    相反,通过实现迭代器,您只需要调用 while($itr->hasNext()) 并处理下一个条目 $itr->next() 返回。清单 3 中显示了一个迭代器示例。迭代器功能强大,因为您可以添加要遍历的新类型条目,并且无需更改遍历条目的代码。例如,在 Person 示例中,可以添加 IM 地址数组;只需更新迭代器,无需更改遍历地址的任何代码。


    清单 3. 使用迭代器模式遍历对象

                    
    class PersonAddressIterator implements AddressIterator
    {
        private $emailAddresses;
        private $physicalAddresses;
        private $position;
        
        public function __construct($emailAddresses)
        {
            $this->emailAddresses = $emailAddresses;
            $this->position = 0;
        }
        
        public function hasNext()
        {
            if ($this->position >= count($this->emailAddresses) || 
                $this->emailAddresses[$this->position] == null) {
                return false;
            } else {
                return true;
            }
        }
        
        public function next()
        {
            $item = $this->emailAddresses[$this->position];
            $this->position = $this->position + 1;
            return $item;
        }
        
    }
    

    如果把 Person 对象修改为返回 AddressIterator 接口的实现,则在将实现扩展为遍历附加对象时无需修改使用迭代器的应用程序代码。您可以使用一个混合迭代器,它封装了遍历清单 3 中列出的每种地址的迭代器。本文提供了此类应用示例(请参阅 下载)。

    图 3 显示了迭代器模式的类图。


    图 3. 迭代器模式的类图
    迭代器模式的类图





    回页首


    装饰器 (decorator) 模式

    考虑清单 4 中的代码样例。这段代码的目的是要把许多功能添加到 Build Your Own Car 站点的汽车中。每个汽车模型都有更多功能及相关价格。如果只针对两个模型,使用 if then 语句添加这些功能十分平常。但是,如果出现了新模型,则必须返回查看代码并确保语句对新模型工作正常。


    清单 4. 使用装饰器模式添加功能

                    
    require('classes.php');
    
    $auto = new Automobile();
    
    $model = new BaseAutomobileModel();
    
    $model = new SportAutomobileModel($model);
    
    $model = new TouringAutomobileModel($model);
    
    $auto->setModel($model);
    
    $auto->printDescription();
    

    进入装饰器模式,该模式允许您通过一个优秀整洁的类将此功能添加到 AutomobileModel。每个类仅仅关注其价格、选项以及添加到基本模型的方式。

    图 4 显示了装饰器模式的类图。


    图 4. 装饰器模式的类图
    装饰器模式的类图

    装饰器模式的优点是可以轻松地同时跟踪库的多个装饰器。

    如果您拥有流对象的使用经验,则一定使用过装饰器。大多数流结构(例如输出流)都是接受基本输入流的装饰器,然后通过添加附加功能来装饰它 —— 例如从文件输入流、从缓冲区输入流,等等。





    回页首


    委托模式

    委托模式将提供一种基于各种条件委托行为的方法。考虑清单 5 中的代码。这段代码包含几个条件。根据条件,代码将选择相应类型的对象来处理请求。


    清单 5. 使用条件语句来发送送货请求

                    
    pkg = new Package("Heavy Package");
    $pkg->setWeight(100);
    
    if ($pkg->getWeight() > 99)
    {
    	echo( "Shipping " . $pkg->getDescription() . " by rail.");
    } else {
    	echo("Shipping " . $pkg->getDescription() . " by truck");
    }
    

    使用委托模式,对象将内在化(internalize)此发送过程,方法为在调用如清单 6 中的 useRail() 之类的方法时设置对相应对象的内部引用。如果处理各个包的条件发生更改或者使用新的送货类型时,则使用此模式尤为便利。


    清单 6. 使用委托模式来发送送货请求

                    
    require_once('classes.php');
    
    $pkg = new Package("Heavy Package");
    $pkg->setWeight(100);
    
    $shipper = new ShippingDelegate();
    
    if ($pkg->getWeight() > 99)
    {
    	$shipper->useRail();
    }
    
    $shipper->deliver($pkg);
    

    委托将通过调用 useRail()useTruck() 方法来切换处理工作的类,从而提供动态更改行为的优点。

    图 5 显示了委托模式的类图。


    图 5. 委托模式的类图
    委托模式的类图





    回页首


    状态模式

    状态模式类似于命令模式,但是意图截然不同。考虑下面的代码。


    清单 7. 使用代码来构建机器人

                    
    class Robot 
    {
    
    	private $state;
    
    	public function powerUp()
    	{
    		if (strcmp($state, "poweredUp") == 0)
    		{
    			echo("Already powered up...\n");
    			/* Implementation... */
    		} else if ( strcmp($state, "powereddown") == 0) {
    			echo("Powering up now...\n");
    			/* Implementation... */
    		}
    	}
    
    	public function powerDown()
    	{
    		if (strcmp($state, "poweredUp") == 0)
    		{
    			echo("Powering down now...\n");
    			/* Implementation... */
    		} else if ( strcmp($state, "powereddown") == 0) {
    			echo("Already powered down...\n");
    			/* Implementation... */
    		}
    	}
    
    	/* etc... */
    
    }
    

    在此清单中,PHP 代码表示变成一辆汽车的强大机器人的操作系统。机器人可以启动、关闭、由汽车变成机器人以及由机器人变成汽车。代码现已就绪,但是您会看到如果任何规则发生更改或者添加另一个状态则会变得十分复杂。

    现在查看清单 8,其中提供了相同的逻辑处理机器人的状态,但是这一次把逻辑放入状态模式。清单 8 中的代码完成的工作与初始代码相同,但是用于处理状态的逻辑已经被放入每个状态的一个对象中。为了演示使用设计模式的优点,假定不久以后,这些机器人发现它们不应在处于机器人模式时关闭。实际上,如果它们关闭,它们必须先切换到汽车模式。如果它们已经处于汽车模式下,则机器人将关闭。使用状态模式,对代码的更改十分微小。


    清单 8. 使用状态模式处理机器人的状态

                    
    $robot = new Robot();
    echo("\n");
    $robot->powerUp();
    echo("\n");
    $robot->turnIntoRobot();
    echo("\n");
    $robot->turnIntoRobot(); /* This one will just give me a message */
    echo("\n");
    $robot->turnIntoVehicle();
    echo("\n");
    


    清单 9. 对一个状态对象的微小更改
                    
    class NormalRobotState implements RobotState
    {
        private $robot;
    
        public function __construct($robot)
        {
            $this->robot = $robot;
        }
    
        public function powerUp()
        {
            /* implementation... */
        }
        public function powerDown()  
        {
            /* First, turn into a vehicle */
            $this->robot->setState(new VehicleRobotState($this->robot));
            $this->robot->powerDown();
        }
        
        public function turnIntoVehicle()  
        {
            /* implementation... */
        }
        
        public function turnIntoRobot() 
        {
            /* implementation... */
        }
    }
    

    图 6 中一个不太明显的地方就是状态模式中的每个对象都有对上下文对象(机器人)的引用,因此每个对象都可以把状态提升到相应的状态。


    图 6. 状态模式的类图
    状态模式的类图

     

     

    结束语

    在 PHP 代码中使用设计模式可以使代码更容易阅读、更易维护。通过使用已经建立的模式,您将从通用的设计结构中获益,从而允许团队的其他开发人员了解代码的意图。它还使您可以从其他设计者完成的工作中获益,因此无需从失败的设计理念中吸取教训。

     

    来源:http://www.ibm.com/developerworks/cn/opensource/os-php-designpatterns


     

    发表于 @ 2008年05月03日 22:39:24|评论(loading...)|编辑

    旧一篇: [转] Erlang十分钟快速入门

    评论

    #qingbai 发表于2008-05-07 18:29:15  IP: 222.90.74.*
    好!
    #SICTXK 发表于2008-05-08 09:03:17  IP: 123.232.120.*
    PHP 的 OO 的确是一大进步!
    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © heiyeluren