<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>潘锦的空间 &#187; 读书总结</title>
	<atom:link href="https://www.phppan.com/tag/%e8%af%bb%e4%b9%a6%e6%80%bb%e7%bb%93/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.phppan.com</link>
	<description>SaaS SaaS架构 团队管理 技术管理 技术架构 PHP 内核 扩展 项目管理</description>
	<lastBuildDate>Sun, 10 May 2026 02:26:45 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.9.40</generator>
	<item>
		<title>开发过程中的偏误</title>
		<link>https://www.phppan.com/2013/12/develop-things-error/</link>
		<comments>https://www.phppan.com/2013/12/develop-things-error/#comments</comments>
		<pubDate>Sun, 08 Dec 2013 03:01:52 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[杂谈]]></category>
		<category><![CDATA[读书总结]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1874</guid>
		<description><![CDATA[开发的一生应当这样度过：当他回首往事的时候，不会因为没有时间陪妹子而悔恨，也不会因为没有浏览过祖国的大好河山而 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>开发的一生应当这样度过：当他回首往事的时候，不会因为没有时间陪妹子而悔恨，也不会因为没有浏览过祖国的大好河山而愧疚。这样，在临终的时候，他就能够说：‘我已把自己整个的生命和全部的精力献给了世界上最壮丽的事业——编程。</p>
<p>作为一个开发人员，每天吭吭哧哧的编码，调试，面对产品MM的需求变更，应对测试MM的各种挑战，呼啦啦，需求上线了，看数据，有告警，马上处理，没有告警，安心做下一个需求，眼睛一睁一闭，一天就过去了，要是一闭不睁呢？</p>
<p>在无比享受的开发过程中，我们可能会存在一些偏误，你见或不见，它就在那里，不增不减，不悲不喜。</p>
<p>在开发的世界中，总会有一种老子天下第一的气势，所谓文无第一，武无第二，开发也是。当一个需求开发完成后，我们都会认为我们的代码是很完美的，它能很好的实现产品的需求，没有bug，当测试MM说开发哥，你这里是不是有bug？第一反应是：怎么可能？是不是环境有问题。这是属于开发的过度自信偏误，但这并不是开发独有的，我们大多数人都有这个问题，只是强弱程度不一样。过度自信偏误对专家的影响比对非专家的影响要大，男人比女人更大，作为以男性居多的开发领域的专家，这个问题比较突出就不奇怪了。</p>
<p>建议：<strong>我们需要基于现场的实际情况做出自己的判断。</strong></p>
<p>隔壁组开始用Go写他们的业务了，NB大发了，要不我们也试试？昨天那个分享中有介绍node.js，现在用的人蛮多的，咱们是不是也用一下试试？现在业内流行特定领域语言，咱们也是不是开发一套……</p>
<p>为什么我们会对大家都在使用的一些东西比较关注？为什么？从众心理。剧场中，当表演到精彩处，有一个人带头鼓起掌来，于是整个剧场都将掌声雷动；喜剧节目或访谈节目时，在关键位置插入笑声往往会引发观众的笑声。如果只是你一个人，也许就没有这样的效果了。<br />
技术人员对技术有着特殊的激情，当一堆人开始讨论某些技术的时候，如果自己不知道一些总会觉得不太和谐，于是开始研究，应用，甚至为这种技术布道。</p>
<p>建议：<strong>对于热门的技术和大家都在谈论的技术，了解可以，具体应用到业务，需要做详细的评估，确认此种技术出现的应用场景，以及是否适用我们当前的业务，一种技术的引进有时是种进步，有时会成为技术负债。</strong></p>
<p>系统告警，组内的人都收到了短信，可这是一个公共模块，谁去处理呢？你想，嗯，总会有人去处理的，于是等啊等啊，终于，一堆的客户投诉到了客服那里，事故升级，大家都挨批了。什么原因？三个和尚没水喝的故事再次重演了呗。如同一堆人一起拉绳子，人越多，个人的贡献越低。这被称之为社会性懈怠，在团队里不仅我们的效率会被克制，我们的责任也会被克制，如同刚才告警的例子，谁也不想为之负责。但这是一种理由性行为：假如使出半力就行，又不会引起注意，为什么要使出全力呢？</p>
<p>建议：<strong>团队业务模块化，责任到人，通过彰显个人效率来缓和这种懈怠。</strong></p>
<p>以上只是我们常遇到的一小部分偏误，不仅仅是我们开发，大部分人也有同样的问题，偏误很多，只是你有没有清醒的认识到？</p>
<p>奇志大兵的相声中有这样一句词：偏爱，偏爱离正爱就不远了吧</p>
<p>偏误也是！</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2013/12/develop-things-error/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>《驱动力》读后总结 &#8211; 是什么驱动了你</title>
		<link>https://www.phppan.com/2012/12/drive/</link>
		<comments>https://www.phppan.com/2012/12/drive/#comments</comments>
		<pubDate>Thu, 06 Dec 2012 23:12:31 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[杂谈]]></category>
		<category><![CDATA[读书总结]]></category>
		<category><![CDATA[读书笔记]]></category>
		<category><![CDATA[马斯洛需求层次理论]]></category>
		<category><![CDATA[驱动力]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1761</guid>
		<description><![CDATA[一本讲述人的书，它会告诉你：是什么驱动了你。作为企业，其核心是经济绩效，而经济绩效依赖于人的绩效，这本书也讲述 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>一本讲述人的书，它会告诉你：是什么驱动了你。作为企业，其核心是经济绩效，而经济绩效依赖于人的绩效，这本书也讲述了怎样可以提高人的绩效，特别是当一些常规手段失效时。在读书过程中反思，现在是什么在驱动自己？自己的动机在哪？这本书有什么内容可以应用到工作中？  有所收获，却也觉得书中所言不能全部信之。</p>
<p>书中介绍人的行为的驱动力有三种：</p>
<ul>
<li>第一种驱动力是生物驱动力，如饿了要吃饭，渴了要喝水，这是1.0时代，生物冲动；</li>
<li>第二种驱动力是外在动机，做出特定行为后外部会带来奖励或惩罚，这是2.0时代，寻求奖励，避免惩罚。</li>
<li>第三种驱动力是内在动机，是我们想要主导我们的生活、延展我们的能力，让生活更有意义的深层欲望。人类的天性决定了他们会寻求对自己命运的掌控权，希望自己引导自己</li>
</ul>
<p>书中作者提出的自我决定理论认为人类有三种内在需求：</p>
<ul>
<li>能力的需求（competence）</li>
<li>自主性的需求（autonomy）</li>
<li>归属的需求（relatedness）</li>
</ul>
<p>看到这些需求，这些驱动力的描述，不得不想起老马的<a href="http://baike.baidu.com/view/295140.htm" target="_blank">基本需求层次理论</a>。该理论将需求分为五种，像阶梯一样从低到高，按层次逐级递升，分别为：生理上的需求，安全上的需求，情感和归属的需求，尊重的需求，自我实现的需求。作者提出的自我决定理论，三个内在需求也是对应老马的理论中的三个层面的，是此理论范围太大，还是？</p>
<p>现在的我们更多的时候是处于第一驱动力或第二驱动力之中，为了生活奔波，这仅仅是因为需要养家糊口。第一驱动力是根本点，其对应到　马斯洛需求层次理论　是最底层的生理上的需求，为了活着。而第二驱动力是从第一驱动力而来，一些内容依赖于第一驱动力。比如奖励和惩罚，其最终的落脚点往往是第一驱动力的一些要素。</p>
<p>作者提到的驱动力3.0，在胡萝卜大棒失效的时代如何提高绩效、焕发热情的三大要素：自主、专精和目的。</p>
<p>驱动力3.0的三大要素</p>
<ul>
<li>自主：我做什么，我决定。这个时代我们并不需要更好的管理，而需要自我管理</li>
<li>专精：把想做的事情做得越来越好。专业是一种痛苦，在通往专精的路上，没有鲜花，没有七色彩虹，在你不想做的时候还得继续做，并且这是一条渐近线。</li>
<li>目的：超越自身的渴望。它是驱动力3.0的内容，驱动力3.0不拒绝利润，但是它强调目的最大化。我们老板常说：我们是在实现自己的梦想，现在只是在实现梦想的过程中顺便赚点钱。忽然想到，现在越来越多的人去创业，他们为了什么？梦想  OR 成功后的经济自由 OR 吃肉自由 OR 自由吃肉？</li>
</ul>
<p>当我们还在为最底层的需求努力时，更上面的需求都是空的，但是如何现在给你高于平均水平的薪酬的同时，再给你更多的自主权，让你一展所长。此时是否有一种士为知己者死的感觉，嗯，要的就是这个。</p>
<p>但是从批判的角度去看上面的这句话：这里的平均水平是什么水平？一展所长是展示什么？自主权能有多自主？是否我们需要把这个平均水平提高，让自己处于更高的水平，此时这样的水平才有些意思，那如何做呢？如作者所说，让你更加的专精。作者提了5点建议：</p>
<ul>
<li>刻意练习的目标是提高成绩。这里更多的是要有目标，即不要太泛，广度是需要的，但是作为程序员来说，深度会更重要些，我们需要找到你专精的目标。</li>
<li>重复、重复、再重复。我很相信1万小时理论：任何人如果想要在某一领域变得十分出色，都需要经过至少1万个小时的练习，才能够达到一个比较高的水平。</li>
<li>想方设法获得批评性意见。知道自己的问题在哪，知道自己改进的方向在哪，才能更好的进步。</li>
<li>关注自己的弱项。我们喜欢做我们擅长的事情，因为我们可以游刃有余，但是对于一个优秀的人来说，关注自己的弱项，在弱项上努力，使之不会成为严重短板。</li>
<li>为身心俱疲做好准备。努力向专精看齐，在这条辛苦的路上，总会有一天你会身心疲惫，也许你会想着放弃，也许你会坚持，向左走，向右走，不同的结果。</li>
</ul>
<p>一个伟大的人，就是一句话，这也应用于一个公司，一个伟大的公司，就是一句话。你的那句话是什么？“为中华之崛起而读书”？“修身齐家治国平天下”？今天的我比昨天更优秀吗？反思，反省。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2012/12/drive/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>再读《程序员修炼之道》总结</title>
		<link>https://www.phppan.com/2012/02/the-pragmatic-programmer/</link>
		<comments>https://www.phppan.com/2012/02/the-pragmatic-programmer/#comments</comments>
		<pubDate>Sat, 18 Feb 2012 13:25:44 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[杂谈]]></category>
		<category><![CDATA[时间是把杀猪刀]]></category>
		<category><![CDATA[读书总结]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1607</guid>
		<description><![CDATA[虽然这本书的中文译名很文艺，但是内容确实值得一看，又花了一个星期的早晨将这本《程序员修炼之道》看了一遍，这次对 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>虽然这本书的中文译名很文艺，但是内容确实值得一看，又花了一个星期的早晨将这本《程序员修炼之道》看了一遍，这次对于每个小节都写了些笔记和摘抄，也许是错的，也许没有什么道理，只是当时的感触和想到的。内容整理如下：</p>
<p>1、我的源码让猫给吃了： 责任、风险、应急备案、不要找借口，真诚</p>
<p>2、软件的熵：破窗户理论、酒与污水理论</p>
<style>
.entry p {margin:13px 5px 0 5px;}
</style>
<p>3、石头汤与煮青蛙： 好的愿景和目标、不谋全局者不足以谋一域</p>
<p>4、足够好的软件：细化非功能性需求、过早优化是万恶之源</p>
<p>5、你的知识资产：养成学习的习惯，知识上的投资总能得到最好的回报</p>
<p>6、交流： 准备好你的交流</p>
<p>7、 重复的危害：DRY原则</p>
<p>8、正交性：高内聚，低耦合；模块化，组件化</p>
<p>9、可撤销性：良好的抽象接口让我们更灵活</p>
<p>10、曳光弹：让程序先跑起来</p>
<p>11、原型与便笺：为了学习，可看不可用。</p>
<p>12、领域语言： 语言会影响你思考问题的方式，合适的才是好的。</p>
<p>13、估算：估算会加深对需求的理解，</p>
<p>14、纯文本的威力：自描述，可读</p>
<p>15、shell游戏：GUI局限了用户的思维，但也提供了一些方便</p>
<p>16、强力编辑：选你所爱的，爱你所选的</p>
<p>17、源码控制：记住过去，人生要是有版本控制会是一个怎样的结果？</p>
<p>18、调试：调试是为了解决问题，心态很重要， 反思BUG产生的原因 </p>
<p>19、 文本操纵：懂一门脚本语言</p>
<p>20、代码生成器：参数化模板，预处理，关注变化的地方</p>
<p>21、按合约设计： DBC，鸭子类型？找出业务规则并封装规则的变化</p>
<p>22、死程序不说谎： switch语句中的default子句的存在是为了让我们发现何时发生了不可能的事情，暴露错误，早崩溃</p>
<p>23、断言式编程：有选择的使用和开启</p>
<p>24、何时使用异常：将异常用于异常的问题</p>
<p>25、怎样配平资源： 处理资源要有始有终，尽量在分配的地方释放</p>
<p>26、 解耦与得墨忒耳法则：最少知识原则，不要和陌生人说话，对象的任何方法都应该只调用它自身、传入此方法的参数、它创建的对象以及它直接持有的组件</p>
<p>27、源程序设计：配置，将变化量放到元数据</p>
<p>28、时间耦合：并发的本质问题之一是时间</p>
<p>29、它只是视图：MVC</p>
<p>30、黑板：mediator模式</p>
<p>31、靠巧合编程： 知道你在做什么，把代码写扎实</p>
<p>32、算法速率：随时记得优化代码，优化要把握度</p>
<p>33、重构：习惯重构，自动测试是比较理想的状况</p>
<p>34、易于测试的代码： 测试文化，你和用户，总有一个人测</p>
<p>35、邪恶的向导：弄清楚向导干了什么</p>
<p>36、需求之坑：将商业策略与实际的需求分开， 问下为什么！需求是需要</p>
<p>37、解开不可能解开的谜题： 确定真正的约束所在</p>
<p>38、等你准备好：构建原型</p>
<p>39、规范陷阱：需求和规范都要有一些抽象，留一些空间</p>
<p>40、圆圈与箭头：取众家之长，形成自己的工作习惯</p>
<p>41、注重实效的团队：个人的原则也适用于团队</p>
<p>42、无处不在的自动化：让计算机去重复，它会比我们做得更好</p>
<p>43、无情的测试：早测试，道是无情却有情</p>
<p>44、全都是写：文档和代码同样重要</p>
<p>45、极大的期望：步子别跨太大，否则会扯到</p>
<p>46、傲慢欲偏见：署名，打上你的标记，树立你的品牌。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2012/02/the-pragmatic-programmer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>无分支开发</title>
		<link>https://www.phppan.com/2012/01/no-branch/</link>
		<comments>https://www.phppan.com/2012/01/no-branch/#comments</comments>
		<pubDate>Wed, 11 Jan 2012 00:53:38 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[项目管理]]></category>
		<category><![CDATA[主干开发]]></category>
		<category><![CDATA[分支开发]]></category>
		<category><![CDATA[版本管理]]></category>
		<category><![CDATA[读书总结]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1563</guid>
		<description><![CDATA[在一个代码库上创建分支的能力是版本控制系统最重要的特性。它的作用是创建一个副本，并将在这个副本上进行操作，从此 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>在一个代码库上创建分支的能力是版本控制系统最重要的特性。它的作用是创建一个副本，并将在这个副本上进行操作，从此它就有了它自己的发展方向，也许有一天会回来，回来时就会合并。分支的作用就是为了更好的帮助并行开发，即在同一时刻能够在两个或更多的工作流上面开发，而不会相互影响。分支开会可以用于哪些应用场景呢？</p>
<style>
.entry p {margin:13px 5px 0 5px;}
</style>
<p>假设我们现在使用的是SVN，并且都是在主干上开发，此时A项目组下在开发，而B项目组准备发布，并且两个项目组中间有一些公共的代码，这个时候就产生了B项目组发布对于A项目组的时间依赖。此时分支开发是一种解决方案。</p>
<p>常见的分支方法有两种：</p>
<ol>
<li>在开发时分支。针对不同的项目或开发团队做分支操作，每个项目或开发团队有一个副本，其所有的操作都在副本上进行，在发布时将分支合并到主干，做整体的合并集成，并做整体发布。这是先分后合的招式。
</li>
<li>在发布时分支。主干上开发完成发布后，创建分支，在分支上修改BUG，当修改的BUG发布时将修改的内容合并到主干。这是先合后分再合的招式。
</li>
</ol>
<p>分支是基于并行开发的一种理想状态，即各个分支是完全独立存在的，并且互不干扰，各成系统。但是现实是各个分支基本上都是有一些关联或依赖的。在开发时可能没有感觉，但是当需要将分支的内容合并时，就会产生较多的冲突和问题，虽然现在的版本控制系统已经在这个方面做得相当好了，但是实际操作中还是会存在一些问题，还是会花费较多的时间。因此在做分支开发时，通常会建议以尽可能高的频率将分支的代码合并到主干净，并且确保主干的正常运行，这样会在一定程序上减缓最终实施合并时的冲突。</p>
<p>什么是无分支开发呢？所谓无分支开发就是指所有的开发工作都在主干上进行，当然这是一种理想情况，但是我们可以尽可能向它靠拢。如果实施了无分支开发，此时就不会存在分支、合并、解决合并冲突等问题了，解决合并冲突的问题最好的方法就是永远不要合并，这和赌博不输的最好的办法就是永远不赌一样。为什么说这是理想情况呢？因为在我们的项目中存在大量的依赖，一个文件或一个类，甚至一个函数可能会被多个人或多个团队修改，如果是多个团队的多个项目并行的话，这咱依赖关系将会影响项目的发布。那么怎么减少这些依赖，嗯，是减少，因为我们基本不可能完全去掉这种依赖，这和我们写代码一样，一些有必要的耦合是完全存在的，并且有其存在的必要性。</p>
<ol>
<li>迪米特法则。迪米特法则（Law of Demeter）又叫作最少知识原则（Least Knowledge Principle 简写LKP），”不要和陌生人说话“，也就是说一个对象应当对其他对象有尽可能少的了解。这是到类级，对象级别的讲究。
</li>
<li>
减小需求的粒度。以一种更加敏捷的方式实现需求，将大的需求分割成小的需求，以增量的方式实现并发布。
</li>
<li>
使用通过抽象来模拟分支的方式实现代码库中大范围的变更。
</li>
<li>
对于公共部分做到文件级的版本发布。即一次发布多个文件的多个版本。
</li>
<li>
使用模块和组件，从功能、团队或变更频率等角度对代码进行切割，以解耦代码间的依赖.
</li>
<li>
将新功能隐藏起来，直到它完成。
</li>
</ol>
<p>以上的几点更适合于小规模团队。</p>
<p>关于第一点，这是面向对象设计的重要原则之一，除此之外，我们经常还会念叨开闭原则，KISS等等。这些都是实现无分支开发时代码级的一些优化措施。</p>
<p>关于第二点，将大的需求变为小的需求本身就是一个比较困难的工作，拆分的原则是什么？粒度以多大 为优，这些都需要依据实现的情况进行判断，以周为单位？以页面为单位？这种方式会比较轻，可以随时停下，即使需求方向有问题，我们也是可以在较少损失的情况下调头。如果我们坚持这样做，那么就意味着我们在解决一个问题：保持应用的持续可工作。</p>
<p>关于第三点，通过抽象来模拟分支的实现步骤如下：</p>
<ol>
<li>
当需求分解后还是无法增量开发或增量开发无法解决问题时，考虑引入中间层或抽象层。使要修改的部分与调用者分离，使其直接低耦合。
</li>
<li>
在需要修改的那部分系统代码上创建一个抽象层。
</li>
<li>
重构系统的其他部分，让他使用这个抽象层。
</li>
<li>
创建一种新的实现代码，在它完成之前不要将它作为产品代码的一部分。
</li>
<li>
更新抽象层，让他使用这个新的实现代码。(如果没有完善的回滚机制，建议在此处做切换开关，即以一个变量控制抽象层的实现，当然，这并不是一个优雅的解决方案)。
</li>
<li>
移除原来的实现代码
</li>
<li>
如果不再需要抽象层，就移除它。
</li>
</ol>
<p>关于第四点，对于公共部分的代码，其修改频率较之其它功能模块更频繁，并且可能存在需要发布旧版本的需求。</p>
<p>关于第五点，模块化，组件化在架构设计中现在已经是非常普遍的行为，但是要想完全模块化或组件化，其难度较大，尽可能的向这方面靠拢，以一定的规则划分模块，针对模块进行设计实现，并在最后将所有模块的结果有机的结合起来。这是在设计层面的分支和合并操作的替代品。</p>
<p>关于第六点，将新功能隐藏起来，直到它完成。这是在没有增量式发布，小步快跑的前提下，或需求确实无法拆分，一组特性一定要一起实现，此时通常会开一个分支做这些新功能的发布，而无分支开发中，可以将这部分代码放在主干，但这些功能对用户不可见，以某种配置项（文件或数据库都行）的方式来操作其对用户的可见性。</p>
<p>读<strong>《持续交付》</strong>总结一</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2012/01/no-branch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>关于耦合</title>
		<link>https://www.phppan.com/2011/08/about-coupling/</link>
		<comments>https://www.phppan.com/2011/08/about-coupling/#comments</comments>
		<pubDate>Wed, 03 Aug 2011 00:55:58 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[程序相关]]></category>
		<category><![CDATA[低耦合]]></category>
		<category><![CDATA[内聚]]></category>
		<category><![CDATA[耦合]]></category>
		<category><![CDATA[读书总结]]></category>
		<category><![CDATA[高内聚]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1436</guid>
		<description><![CDATA[在做程序设计时我们经常会听到“高内聚，低耦合”，这是我们追求的目标。 其中内聚是指一个模块内各个元素彼此结合的 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p style="text-indent: 2em;">在做程序设计时我们经常会听到“高内聚，低耦合”，这是我们追求的目标。 其中内聚是指一个模块内各个元素彼此结合的紧密程度， 高内聚是指一个模块或一个类内部各个元素之间关系紧密，争取用最少的元素和方法实现相应的功能； 耦合是指模块之间互相关联程度的度量， 而低耦合是指一个程序中各个模块之间的联系少和相互依赖程度低，一个模块只需要具体实现一个功能。 总的来说，我们所追求的设计是这样的，每个模块职责单一，一个模块只完成一个相对独立的特定子功能，并且和其他模块之间的关系简单（嗯，保持简单), 在不同的应用场景下复用这些模块，从而组成新的系统或大的模块。</p>
<p style="text-indent: 2em;">在编写代码的过程中，我们应该尽量实现程序的内聚性。内聚性差的程序通常会让人产生这里什么都有，一片杂乱的景象， 特别是那种将类作为若干不同功能函数集的设计。和内聚性差一样，也会让人产生不好情绪还有高耦合。 耦合就是一些代码或一些模块对另一些代码或模块的依赖。而依赖破坏了当初的分块，严重的模块间耦合会让当初的模块化的设想付之一炬。 虽然这种耦合产生的依赖不是很好，但是我们并不能消除耦合。因为正是这种耦合，各种程序模块才能产生互操作。 所以我们只能在允许的范围内尽量减少不必要的耦合。</p>
<p style="text-indent: 2em;">我们可以将耦合分为以下三类：</p>
<ol>
<li>可以接受的耦合</li>
<li>不建议使用的耦合</li>
<li>真的不建议使用的耦合</li>
</ol>
<p style="text-indent: 2em;">直接看这三个分类真没啥意义，关键是这些分类中所包含的耦合实例。</p>
<h2 style="font-weight: bold; font-family: 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 1.2em; color: #333333;">可以接受的耦合</h2>
<p style="text-indent: 2em;">可用的耦合是指这种耦合会经常存在，而且有时也必须存在，其害处不大。如数据耦合和标记耦合。 何为 <strong>数据耦合</strong>，看这样一个例子：</p>
<pre style="background-color: #333333; color: #ffffff; font: normal normal normal 13px/normal 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Courier New', monospace; overflow-x: auto; overflow-y: auto; padding: 10px;"><span style="color: #cc7833;">function</span> main<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
    output_name<span style="color: #ffffff;">(</span><span style="color: #56db3a;">'name'</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>
<span style="color: #ffffff;">}</span>

<span style="color: #cc7833;">function</span> output_name<span style="color: #ffffff;">(</span><span style="color: #6d9cbe;">$name</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
    <a style="color: #1299da; text-decoration: none;" href="http://www.php.net/echo"><span style="color: #e2392d;">echo</span></a> <span style="color: #6d9cbe;">$name</span><span style="color: #e0882f;">;</span>
<span style="color: #ffffff;">}</span>
main<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span></pre>
<p style="text-indent: 2em;">这种以函数间传递参数的方式产生的函数是不可避免的，这对程序没有太大的影响。</p>
<p style="text-indent: 2em;"><strong>标记耦合</strong> 是指将一个大的数据结构或类传递给另一个模块或类，而该模块只需要这个数据结构的一小部分，或只需要这个类的一个属性值。 以传递为类为例:</p>
<pre style="background-color: #333333; color: #ffffff; font: normal normal normal 13px/normal 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Courier New', monospace; overflow-x: auto; overflow-y: auto; padding: 10px;"><span style="color: #cc7833;">class</span> Foo <span style="color: #ffffff;">{</span>
    <span style="color: #cc7833;">private</span> <span style="color: #6d9cbe;">$_name</span><span style="color: #e0882f;">;</span>

    <span style="color: #cc7833;">public</span> <span style="color: #cc7833;">function</span> __construct<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
        <span style="color: #6d9cbe;">$this</span><span style="color: #e0882f;">-&gt;</span>_name <span style="color: #e0882f;">=</span> <span style="color: #cc7833;">__CLASS__</span><span style="color: #e0882f;">;</span>
    <span style="color: #ffffff;">}</span>

    <span style="color: #cc7833;">public</span> <span style="color: #cc7833;">function</span> getName<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
        <span style="color: #ff8400;">return</span> <span style="color: #6d9cbe;">$this</span><span style="color: #e0882f;">-&gt;</span>_name<span style="color: #e0882f;">;</span>
    <span style="color: #ffffff;">}</span>
<span style="color: #ffffff;">}</span>

<span style="color: #cc7833;">function</span> output_name<span style="color: #ffffff;">(</span>Foo <span style="color: #6d9cbe;">$foo</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
    <a style="color: #1299da; text-decoration: none;" href="http://www.php.net/echo"><span style="color: #e2392d;">echo</span></a> <span style="color: #6d9cbe;">$foo</span><span style="color: #e0882f;">-&gt;</span><span style="color: #ffffff;">getName</span><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>
<span style="color: #ffffff;">}</span>

output_name<span style="color: #ffffff;">(</span><span style="color: #cc7833;">new</span> Foo<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span></pre>
<p style="text-indent: 2em;">其实我们应该是将getName()的输出直接传递给输出函数。 标记函数在一定程序上阻碍了我们对于程序的理解，因为我们需要去了解这个程序到底调用了类中的哪一个方法或使用了数据结构中的哪一个属性。</p>
<h2 style="font-weight: bold; font-family: 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 1.2em; color: #333333;">不建议使用的耦合</h2>
<p style="text-indent: 2em;">不建议使用的耦合是指那种我们会经常见到的不会影响整体的架构，但是有一些坏味道的代码，如控制耦合，时间耦合</p>
<p style="text-indent: 2em;"><strong>控制耦合</strong> 是指一个函数传递的某个参数影响另一个函数中所作的控制决定。有时候这种实现只是为了复用一些代码。 如下示例：</p>
<pre style="background-color: #333333; color: #ffffff; font: normal normal normal 13px/normal 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Courier New', monospace; overflow-x: auto; overflow-y: auto; padding: 10px;">function edit($is_add = 0) {
    if ($is_add) {
        //  一些需要添加的字段
    }else{
        //  一些编辑的字段
    }

    //  公共的字段
    //  保存数据
}</pre>
<p style="text-indent: 2em;">以上的示例只是想复用编辑和添加的操作中一些公共的东西，从而引入是否是添加操作的变量。 如果要重构以上代码，可以将一个函数分为三个函数，添加和修改各是一个，公共代码放一个函数。</p>
<p style="text-indent: 2em;"><strong>时间耦合</strong> 是指代码中各个元素之间依赖于时间的关系， 以类的public方法调用为例，如果一个方法A在调用时需要先调用另一个方法B，则这里就是时间耦合。 看一个示例：</p>
<pre style="background-color: #333333; color: #ffffff; font: normal normal normal 13px/normal 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Courier New', monospace; overflow-x: auto; overflow-y: auto; padding: 10px;"><span style="color: #cc7833;">class</span> <a style="color: #1299da; text-decoration: none;" href="http://www.php.net/file"><span style="color: #e2392d;">File</span></a> <span style="color: #ffffff;">{</span>

    <span style="color: #cc7833;">private</span> <span style="color: #6d9cbe;">$_path</span><span style="color: #e0882f;">;</span>

    <span style="color: #cc7833;">public</span> <span style="color: #cc7833;">function</span> __construct<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>

    <span style="color: #ffffff;">}</span>

    <span style="color: #cc7833;">public</span> <span style="color: #cc7833;">function</span> read<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
        <a style="color: #1299da; text-decoration: none;" href="http://www.php.net/echo"><span style="color: #e2392d;">echo</span></a> <span style="color: #56db3a;">'read file from '</span><span style="color: #e0882f;">,</span> <span style="color: #6d9cbe;">$this</span><span style="color: #e0882f;">-&gt;</span>_path<span style="color: #e0882f;">,</span> <span style="color: #56db3a;">'&lt;br /&gt;'</span><span style="color: #e0882f;">;</span>
    <span style="color: #ffffff;">}</span>

    <span style="color: #cc7833;">public</span> <span style="color: #cc7833;">function</span> setPath<span style="color: #ffffff;">(</span><span style="color: #6d9cbe;">$path</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
        <span style="color: #6d9cbe;">$this</span><span style="color: #e0882f;">-&gt;</span>_path <span style="color: #e0882f;">=</span> <span style="color: #6d9cbe;">$path</span><span style="color: #e0882f;">;</span>
    <span style="color: #ffffff;">}</span>
<span style="color: #ffffff;">}</span>

<span style="color: #6d9cbe;">$file</span> <span style="color: #e0882f;">=</span> <span style="color: #cc7833;">new</span> <a style="color: #1299da; text-decoration: none;" href="http://www.php.net/file"><span style="color: #e2392d;">File</span></a><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>
<span style="color: #6d9cbe;">$file</span><span style="color: #e0882f;">-&gt;</span><span style="color: #ffffff;">setPath</span><span style="color: #ffffff;">(</span><span style="color: #cc7833;">__FILE__</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>
<span style="color: #6d9cbe;">$file</span><span style="color: #e0882f;">-&gt;</span><span style="color: #ffffff;">read</span><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span></pre>
<p style="text-indent: 2em;">以上是一个示例性质的文件类，在读取一个文件的文件内容之前需要先设置这个文件所在的地址。 这种形式的时间耦合应该尽量避免，如果要重构这样的代码，可以将路径作为一个变量传递给构造函数。</p>
<h2 style="font-weight: bold; font-family: 'Microsoft YaHei', Helvetica, Arial, sans-serif; font-size: 1.2em; color: #333333;">真的不建议使用的耦合</h2>
<p style="text-indent: 2em;">这类耦合一旦出现，虽然不会赤地千里，但会严重影响整体的架构和模块间的关联。如公用耦合</p>
<p style="text-indent: 2em;"><strong>公用耦合</strong> 通俗的讲，公共耦合就是使用了全局变量。当两个函数或两个模块访问同一个全局变量时，它们就被公用耦合了。 在PHP中一些全局变量$_GET，$_POST等经常会在一些代码中用到，如果有两段代码都使用了这些变量并且修改了同一个值，但是双方互不相知，此时就会出BUG。</p>
<p style="text-indent: 2em;"><strong>领域耦合</strong> 指的是在应用的代码中嵌入了领域或商业知识与规则，简单的讲就是将业务规则硬编码到应用中，为一些特定的业务定制应用。 这在我们的开发中会经常出现，一般会通过配置或特定的领域语言减轻系统某些部分因为耦合带来的问题。</p>
<p style="text-indent: 2em;">以上的各种耦合的定义都来自《高质量程序设计艺术》一书。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2011/08/about-coupling/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP设计模式笔记：使用PHP实现备忘录模式</title>
		<link>https://www.phppan.com/2010/10/php-design-pattern-18-memento/</link>
		<comments>https://www.phppan.com/2010/10/php-design-pattern-18-memento/#comments</comments>
		<pubDate>Sat, 09 Oct 2010 05:39:25 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[设计模式]]></category>
		<category><![CDATA[读书总结]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1022</guid>
		<description><![CDATA[PHP设计模式笔记：使用PHP实现备忘录模式 【意图】 在不破坏封装性的前提下，捕获一个对象的内部状态，并在该 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP设计模式笔记：使用PHP实现备忘录模式</p>
<p><strong>【意图】</strong><br />
在不破坏封装性的前提下，捕获一个对象的内部状态，并在该对象之外保存这个状态。这样可以在以后把该对象的状态恢复到之前保存的状态。【GOF95】</p>
<p><strong>【备忘录模式结构图】</strong><br />
<div id="attachment_1023" style="width: 432px" class="wp-caption aligncenter"><a href="http://www.phppan.com/wp-content/uploads/2010/10/Memento.jpg"><img src="http://www.phppan.com/wp-content/uploads/2010/10/Memento.jpg" alt="备忘录模式" title="Memento" width="422" height="145" class="size-full wp-image-1023" /></a><p class="wp-caption-text">备忘录模式</p></div></p>
<p><strong>【备忘录模式中主要角色】</strong><br />
1、备忘录(Memento)角色：<br />
存储发起人(Originator)对象的内部状态，而发起人根据需要决定备忘录存储发起人的哪些内部状态。<br />
备忘录可以保护其内容不被发起人(Originator)对象之外的任何对象所读取。</p>
<p>2、发起人(Originator)角色：<br />
创建一个含有当前的内部状态的备忘录对象<br />
使用备忘录对象存储其内部状态</p>
<p>3、负责人(Caretaker)角色：<br />
负责保存备忘录对象，不检查备忘录对象的内容</p>
<p><strong>【备忘录模式的优点和缺点】</strong><br />
备忘录模式的优点：<br />
1、有时一些发起人对象的内部信息必须保存在发起人对象以外的地方，但是必须要由发起人对象自己读取。<br />
2、简化了发起人(Originator)类。发起人(Originator)不再需要管理和保存其内部状态的一个个版本，客户端可以自行管理它们所需要的这些状态的版本<br />
3、当发起人角色的状态改变的时候，有可能这个状态无效，这时候就可以使用暂时存储起来的备忘录将状态复原。</p>
<p>备忘录模式的缺点：<br />
1、如果发起人角色的状态需要完整地存储到备忘录对象中，那么在资源消耗上面备忘录对象会很昂贵。<br />
2、当负责人角色将一个备忘录存储起来的时候，负责人可能并不知道这个状态会占用多大的存储空间，从而无法提醒用户一个操作是否会很昂贵。<br />
3、当发起人角色的状态改变的时候，有可能这个状态无效。</p>
<p><strong>【备忘录模式适用场景】</strong><br />
1、必须保存一个对象在某一个时刻的（部分）状态，这样以后需要时它才能恢复到先前的状态。<br />
2、如果一个用接口来让其它对象直接得到这些状态，将会暴露对象的实现细节并破坏对象的封装性。</p>
<p><strong>【备忘录模式与其它模式】</strong><br />
1、<a href=" http://www.phppan.com/2010/08/php-design-pattern-15-command/">命令模式(command模式)</a>：Command模式也可以用来恢复对象的状态，一般Command模式可以支持多级状态的回滚，Memento只是简单的恢复（快照）。在Command模式的每一个undo中，可以使用Memento来保存对象的状态。<br />
2、迭代器模式(Iterator模式)：备忘录可以用于迭代</p>
<p><strong>【备忘录模式PHP示例】</strong></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 备忘录模式 2010-10-09 sz
 * @author phppan.p#gmail.com  http://www.phppan.com                                                       
 * 哥学社成员（http://www.blog-brother.com/）
 * @package design pattern
 */</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 发起人(Originator)角色
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Originator <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_state</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_state <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 创建备忘录
     * @return Memento 包含当前状态的备忘录对象
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> createMemento<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">new</span> Memento<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_state<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 将发起人恢复到备忘录对象记录的状态上
     * @param Memento $memento
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> restoreMemento<span style="color: #009900;">&#40;</span>Memento <span style="color: #000088;">$memento</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_state <span style="color: #339933;">=</span> <span style="color: #000088;">$memento</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getState</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setState<span style="color: #009900;">&#40;</span><span style="color: #000088;">$state</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_state <span style="color: #339933;">=</span> <span style="color: #000088;">$state</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getState<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_state<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 测试用方法，显示状态
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> showState<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;Original Status:&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getState</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;&lt;br /&gt;&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 备忘录(Memento)角色
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Memento <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_state</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$state</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setState</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$state</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getState<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_state<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setState<span style="color: #009900;">&#40;</span><span style="color: #000088;">$state</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_state <span style="color: #339933;">=</span> <span style="color: #000088;">$state</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 负责人(Caretaker)角色
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Caretaker <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_memento</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getMemento<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_memento<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setMemento<span style="color: #009900;">&#40;</span>Memento <span style="color: #000088;">$memento</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_memento <span style="color: #339933;">=</span> <span style="color: #000088;">$memento</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 客户端
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Client <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Main program.
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">/* 创建目标对象 */</span>
        <span style="color: #000088;">$org</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Originator<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$org</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setState</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'open'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$org</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">showState</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">/* 创建备忘 */</span>
        <span style="color: #000088;">$memento</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$org</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">createMemento</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">/* 通过Caretaker保存此备忘 */</span>
        <span style="color: #000088;">$caretaker</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Caretaker<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$caretaker</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setMemento</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$memento</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">/* 改变目标对象的状态 */</span>
        <span style="color: #000088;">$org</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setState</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'close'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$org</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">showState</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">/* 还原操作 */</span>
        <span style="color: #000088;">$org</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">restoreMemento</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$caretaker</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMemento</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$org</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">showState</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
Client<span style="color: #339933;">::</span><span style="color: #004000;">main</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/10/php-design-pattern-18-memento/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP设计模式笔记：使用PHP实现观察者模式</title>
		<link>https://www.phppan.com/2010/09/php-design-pattern-17-observer/</link>
		<comments>https://www.phppan.com/2010/09/php-design-pattern-17-observer/#comments</comments>
		<pubDate>Thu, 23 Sep 2010 16:32:24 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[设计模式]]></category>
		<category><![CDATA[读书总结]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1008</guid>
		<description><![CDATA[PHP设计模式笔记：使用PHP实现观察者模式 【意图】 定义对象间的一种一对多的依赖关系，当一个对象的状态发生 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP设计模式笔记：使用PHP实现观察者模式</p>
<p><strong>【意图】</strong><br />
定义对象间的一种一对多的依赖关系，当一个对象的状态发生改变时，所有依赖于它的对象都得到通知并被自动更新【GOF95】<br />
又称为发布-订阅（Publish-Subscribe）模式、模型-视图（Model-View）模式、源-监听（Source-Listener）模式、或从属者(Dependents)模式</p>
<p><strong>【观察者模式结构图】</strong><br />
<div id="attachment_1009" style="width: 377px" class="wp-caption aligncenter"><a href="http://www.phppan.com/wp-content/uploads/2010/09/Observer.jpg"><img src="http://www.phppan.com/wp-content/uploads/2010/09/Observer.jpg" alt="观察者模式" title="Observer" width="367" height="342" class="size-full wp-image-1009" /></a><p class="wp-caption-text">观察者模式</p></div></p>
<p><strong>【观察者模式中主要角色】</strong><br />
抽象主题（Subject）角色：主题角色将所有对观察者对象的引用保存在一个集合中，每个主题可以有任意多个观察者。抽象主题提供了增加和删除观察者对象的接口。<br />
抽象观察者（Observer）角色：为所有的具体观察者定义一个接口，在观察的主题发生改变时更新自己。<br />
具体主题（ConcreteSubject）角色：存储相关状态到具体观察者对象，当具体主题的内部状态改变时，给所有登记过的观察者发出通知。具体主题角色通常用一个具体子类实现。<br />
具体观察者（ConcretedObserver）角色：存储一个具体主题对象，存储相关状态，实现抽象观察者角色所要求的更新接口，以使得其自身状态和主题的状态保持一致。</p>
<p><strong>【观察者模式的优点和缺点】</strong><br />
观察者模式的优点：<br />
1、观察者和主题之间的耦合度较小；<br />
2、支持广播通信；</p>
<p>观察者模式的缺点：<br />
1、由于观察者并不知道其它观察者的存在，它可能对改变目标的最终代价一无所知。这可能会引起意外的更新。</p>
<p><strong>【观察者模式适用场景】</strong><br />
1、当一个抽象模型有两个方面，其中一个方面依赖于另一个方面。<br />
2、当对一个对象的改变需要同时改变其它对象，而不知道具体有多少个对象待改变。<br />
3、当一个对象必须通知其它对象，而它又不能假定其它对象是谁。换句话说，你不希望这些对象是紧密耦合的。</p>
<p><strong>【观察者模式与其它模式】</strong><br />
中介者模式（Mediator）:通过封装复杂的更新语义，ChangeManager充当目标和观察者之间的中介者。<br />
<a href="http://www.phppan.com/2010/06/php-design-pattern-6-singleton/">单例模式(singleton模式)</a>：ChangeManager可使用Singleton模式来保证它是唯一的并且是可全局访问的。</p>
<p><strong>【观察者模式PHP示例】</strong></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 观察者模式 2010-09-23 sz
 * @author phppan.p#gmail.com  http://www.phppan.com                                             
 * 哥学社成员（http://www.blog-brother.com/）
 * @package design pattern
 */</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 抽象主题角色
 */</span>
<span style="color: #000000; font-weight: bold;">interface</span> Subject <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 增加一个新的观察者对象
     * @param Observer $observer
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> attach<span style="color: #009900;">&#40;</span>Observer <span style="color: #000088;">$observer</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 删除一个已注册过的观察者对象
     * @param Observer $observer
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> detach<span style="color: #009900;">&#40;</span>Observer <span style="color: #000088;">$observer</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 通知所有注册过的观察者对象
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> notifyObservers<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 具体主题角色
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> ConcreteSubject implements Subject <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_observers</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_observers <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 增加一个新的观察者对象
     * @param Observer $observer
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> attach<span style="color: #009900;">&#40;</span>Observer <span style="color: #000088;">$observer</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #990000;">array_push</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_observers<span style="color: #339933;">,</span> <span style="color: #000088;">$observer</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 删除一个已注册过的观察者对象
     * @param Observer $observer
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> detach<span style="color: #009900;">&#40;</span>Observer <span style="color: #000088;">$observer</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$index</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_search</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$observer</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_observers<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$index</span> <span style="color: #339933;">===</span> <span style="color: #009900; font-weight: bold;">FALSE</span> <span style="color: #339933;">||</span> <span style="color: #339933;">!</span> <span style="color: #990000;">array_key_exists</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$index</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_observers<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">FALSE</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_observers<span style="color: #009900;">&#91;</span><span style="color: #000088;">$index</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 通知所有注册过的观察者对象
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> notifyObservers<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">is_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_observers<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">FALSE</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_observers <span style="color: #b1b100;">as</span> <span style="color: #000088;">$observer</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$observer</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">update</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 抽象观察者角色
 */</span>
<span style="color: #000000; font-weight: bold;">interface</span> Observer <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 更新方法
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> update<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> ConcreteObserver implements Observer <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 观察者的名称
     * @var &lt;type&gt;
     */</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_name</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_name <span style="color: #339933;">=</span> <span style="color: #000088;">$name</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 更新方法
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> update<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'Observer'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_name<span style="color: #339933;">,</span> <span style="color: #0000ff;">' has notified.&lt;br /&gt;'</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 客户端
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Client <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Main program.
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$subject</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ConcreteSubject<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">/* 添加第一个观察者 */</span>
        <span style="color: #000088;">$observer1</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ConcreteObserver<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Martin'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$subject</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">attach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$observer1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'&lt;br /&gt; The First notify:&lt;br /&gt;'</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$subject</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">notifyObservers</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">/* 添加第二个观察者 */</span>
        <span style="color: #000088;">$observer2</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ConcreteObserver<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'phppan'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$subject</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">attach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$observer2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'&lt;br /&gt; The Second notify:&lt;br /&gt;'</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$subject</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">notifyObservers</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">/* 删除第一个观察者 */</span>
        <span style="color: #000088;">$subject</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">detach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$observer1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'&lt;br /&gt; The Third notify:&lt;br /&gt;'</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$subject</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">notifyObservers</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
Client<span style="color: #339933;">::</span><span style="color: #004000;">main</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/09/php-design-pattern-17-observer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP设计模式笔记：使用PHP实现模板方法模式</title>
		<link>https://www.phppan.com/2010/09/php-design-pattern-16-template-method/</link>
		<comments>https://www.phppan.com/2010/09/php-design-pattern-16-template-method/#comments</comments>
		<pubDate>Sun, 12 Sep 2010 06:05:50 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[设计模式]]></category>
		<category><![CDATA[读书总结]]></category>
		<category><![CDATA[面向对象]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=984</guid>
		<description><![CDATA[PHP设计模式笔记：使用PHP实现模板方法模式 【意图】 定义一个操作中的算法的骨架，而将一些步骤延迟到子类中 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP设计模式笔记：使用PHP实现模板方法模式</p>
<p><strong>【意图】</strong><br />
定义一个操作中的算法的骨架，而将一些步骤延迟到子类中。Template Method 使得子类可以在不改变一个算法的结构的情况下重定义该算法的某些特定的步骤【GOF95】</p>
<p><strong>【模板方法模式结构图】</strong><br />
<div id="attachment_985" style="width: 316px" class="wp-caption aligncenter"><a href="http://www.phppan.com/wp-content/uploads/2010/09/Template.jpg"><img src="http://www.phppan.com/wp-content/uploads/2010/09/Template.jpg" alt="Template Method" title="Template Method" width="306" height="194" class="size-full wp-image-985" /></a><p class="wp-caption-text">Template Method</p></div></p>
<p><strong>【模板方法模式中主要角色】</strong><br />
抽象模板(AbstractClass)角色: 定义一个或多个抽象方法让子类实现。这些抽象方法叫做基本操作，它们是顶级逻辑的组成部分。<br />
定义一个模板方法。这个模板方法一般是一个具体方法，它给出顶级逻辑的骨架，而逻辑的组成步骤在对应的抽象操作中，这些操作将会推迟到子类中实现。同时，顶层逻辑也可以调用具体的实现方法</p>
<p>具体模板(ConcrteClass)角色：实现父类的一个或多个抽象方法，作为顶层逻辑的组成而存在。</p>
<p>每个抽象模板可以有多个具体模板与之对应，而每个具体模板有其自己对抽象方法（也就是顶层逻辑的组成部分）的实现，从而使得顶层逻辑的实现各不相同。</p>
<p><strong>【模板方法模式适用场景】</strong><br />
1、一次性实现一个算法的不变的部分，并将可变的行为留给子类来实现。<br />
2、各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。<br />
3、控制子类扩展。</p>
<p><strong>【模板方法模式与其它模式】</strong><br />
1、<a href="http://www.phppan.com/2010/07/php-design-pattern-12-strategy/">策略模式(strategy模式)</a>：模板方法使用继承来改变算法的部分，策略模式使用委托来改变整个算法。区别在于封闭的变化不同，一个变化的部分，一个变化的是整体。<br />
2、<a href="http://www.phppan.com/2010/07/php-design-pattern-9-factory-method/">工厂方法模式(factory method模式)</a>：Factory Method模式常被模板方法调用。<br />
<strong>【模板方法模式PHP示例】</strong></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #009933; font-style: italic;">/**
 * 模板方法模式简单示例 2010-09-12 sz
 * @author phppan.p#gmail.com  http://www.phppan.com                                                       
 * 哥学社成员（http://www.blog-brother.com/）
 * @package design pattern
 */</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 抽象模板角色
 * 定义抽象方法作为顶层逻辑的组成部分，由子类实现
 * 定义模板方法作为顶层逻辑的架子，调用基本方法组装顶层逻辑
 */</span>
<span style="color: #000000; font-weight: bold;">abstract</span> <span style="color: #000000; font-weight: bold;">class</span> AbstractClass <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 模板方法 调用基本方法组装顶层逻辑
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> templateMethod<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'templateMethod begin.&lt;br /&gt;'</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">primitiveOperation1</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">primitiveOperation2</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'templateMethod end.&lt;br /&gt;'</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 基本方法1
     */</span>
    <span style="color: #000000; font-weight: bold;">abstract</span> <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> primitiveOperation1<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
     <span style="color: #009933; font-style: italic;">/**
     * 基本方法2
     */</span>
    <span style="color: #000000; font-weight: bold;">abstract</span> <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> primitiveOperation2<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 具体模板角色
 * 实现父类的抽象方法
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> ConcreteClass <span style="color: #000000; font-weight: bold;">extends</span> AbstractClass<span style="color: #009900;">&#123;</span>
    <span style="color: #009933; font-style: italic;">/**
     * 基本方法1
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> primitiveOperation1<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'primitiveOperation1&lt;br /&gt;'</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
     <span style="color: #009933; font-style: italic;">/**
     * 基本方法2
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> primitiveOperation2<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'primitiveOperation2&lt;br /&gt;'</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 客户端
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Client <span style="color: #009900;">&#123;</span>
&nbsp;
     <span style="color: #009933; font-style: italic;">/**
     * Main program.
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$class</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ConcreteClass<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$class</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">templateMethod</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
Client<span style="color: #339933;">::</span><span style="color: #004000;">main</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p><strong>【模板方法模式】</strong><br />
模板方法是一种代码复用的基本技术，模板方法导致一种反射的控制结构，这指的是一个父类调用子类的操作。<br />
其实现过程：准备一个抽象类，将部分逻辑以具体方法以及具体构造子的形式实现，然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同子类可以以不同的方式实现这些抽象方法，从而对剩余的逻辑有不同的实现。</p>
<p><strong>【重构的原则】</strong><br />
重构时应当遵守的原则是：将行为以是移到结构的高端，而将状态尽量移动到结构的低端。<br />
Auer曾在文献【AUER95】中指出：<br />
1、应当要所行为而不是状态定义一个类。<br />
2、在实现行为是，是用抽象状态而不是用具体状态。<br />
3、给操作划分层次。<br />
4、将状态的确认推迟到子类中。在父类中，如果需要状态属性的话，可以调用抽象的取值方法，而将抽象的取值方法的实现放到具体子类中。<br />
如果可以遵守以上的而，那么就可以在等级结构中将接口与实现分离，将抽象与具体分离，从而保证代码可以最大限度的被复用。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/09/php-design-pattern-16-template-method/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP设计模式笔记：使用PHP实现命令模式</title>
		<link>https://www.phppan.com/2010/08/php-design-pattern-15-comman/</link>
		<comments>https://www.phppan.com/2010/08/php-design-pattern-15-comman/#comments</comments>
		<pubDate>Mon, 23 Aug 2010 00:41:10 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[设计模式]]></category>
		<category><![CDATA[读书总结]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=933</guid>
		<description><![CDATA[PHP设计模式笔记：使用PHP实现命令模式 【意图】 将一个请求封装为一个对象，从而使用你可用不同的请求对客户 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP设计模式笔记：使用PHP实现命令模式</p>
<p><strong>【意图】</strong><br />
将一个请求封装为一个对象，从而使用你可用不同的请求对客户进行参数化；对请求排队或记录请求日志，以及支持可撤消的操作。<br />
可变的方面是:何时，怎样满足一个请求<br />
<strong>命令模式是对命令的封装。命令模式把发出命令的责任和执行命令的责任分割开，委派给不同的对象。</strong><br />
请求的一方发出请求要求执行一个操作；接收的一方收到请求，并执行操作。命令模式允许请求的一方和接收的一方独立开来，使得请求的一方不必知道接收请求的一方的接口，更不必知道请求是怎么被接收，以及操作是否被执行、何时被执行，以及是怎么被执行的。</p>
<p><strong>【命令模式结构图】</strong><br />
<div id="attachment_934" style="width: 379px" class="wp-caption aligncenter"><a href="http://www.phppan.com/wp-content/uploads/2010/08/Command.jpg"><img class="size-full wp-image-934" title="Command模式" src="http://www.phppan.com/wp-content/uploads/2010/08/Command.jpg" alt="Command模式" width="369" height="248" /></a><p class="wp-caption-text">Command模式</p></div></p>
<p><strong>【命令模式中主要角色】</strong><br />
命令（Command）角色：声明了一个给所有具体命令类的抽象接口。这是一个抽象角色。<br />
具体命令（ConcreteCommand）角色：定义一个接受者和行为之间的弱耦合；实现Execute()方法，负责调用接收考的相应操作。Execute()方法通常叫做执行方法。<br />
客户（Client）角色：创建了一个具体命令(ConcreteCommand)对象并确定其接收者。<br />
请求者（Invoker）角色：负责调用命令对象执行请求，相关的方法叫做行动方法。<br />
接收者（Receiver）角色：负责具体实施和执行一个请求。任何一个类都可以成为接收者，实施和执行请求的方法叫做行动方法。</p>
<p><strong>【命令模式的优点】</strong><br />
命令模式的优点：<br />
1、命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分离开。<br />
2、命令类与其他任何别的类一样，可以修改和推广。<br />
3、可以把命令对象聚合在一起，合成为合成命令。<br />
4、可以很容易的加入新的命令类。<br />
命令模式的缺点：可能会导致某些系统有过多的具体命令类。</p>
<p><strong>【命令模式适用场景】</strong><br />
1、抽象出待执行的动作以参数化对象。Command模式是回调机制的一个面向对象的替代品。<br />
2、在不同的时刻指定、排列和执行请求。<br />
3、支持取消操作。<br />
4、支持修改日志。<br />
5、用构建在原语操作上的高层操作构造一个系统。Command模式提供了对事务进行建模的方法。Command有一个公共的接口，使得你可以用同一种方式调用所有的事务。同时使用该模式也易于添加新事务以扩展系统。</p>
<p><strong>【命令模式与其它模式】</strong><br />
<a href="http://www.phppan.com/2010/08/php-design-pattern-14-composite/">合成模式(composite模式)</a>:Composite模式可被实现宏命令<br />
<a href="http://www.phppan.com/2010/06/php-design-pattern-8-prototype/">原型模式(prototype模式)</a>：如果命令类带有clone(或在之前的文章中提到的copy方法)方法，命令就可以被复制。在命令模式支持多次取消操作时可能需要用到此模式，以复制当前状态的Command对象</p>
<p><strong>【命令模式PHP示例】</strong></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #009933; font-style: italic;">/**
 * 命令模式 2010-08-21 sz
 * @author phppan.p#gmail.com  http://www.phppan.com                                                       
 * 哥学社成员（http://www.blog-brother.com/）
 * @package design pattern
 */</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 命令角色
 */</span>
<span style="color: #000000; font-weight: bold;">interface</span> Command <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 执行方法
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> execute<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 具体命令角色
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> ConcreteCommand implements Command <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_receiver</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span>Receiver <span style="color: #000088;">$receiver</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_receiver <span style="color: #339933;">=</span> <span style="color: #000088;">$receiver</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 执行方法
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> execute<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_receiver<span style="color: #339933;">-&gt;</span><span style="color: #004000;">action</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 接收者角色
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Receiver <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">/* 接收者名称 */</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_name</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_name <span style="color: #339933;">=</span> <span style="color: #000088;">$name</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 行动方法
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> action<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_name<span style="color: #339933;">,</span> <span style="color: #0000ff;">' do action.&lt;br /&gt;'</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 请求者角色
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Invoker <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_command</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span>Command <span style="color: #000088;">$command</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_command <span style="color: #339933;">=</span> <span style="color: #000088;">$command</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> action<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_command<span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 客户端
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Client <span style="color: #009900;">&#123;</span>
&nbsp;
     <span style="color: #009933; font-style: italic;">/**
     * Main program.
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$receiver</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Receiver<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'phpppan'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$command</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ConcreteCommand<span style="color: #009900;">&#40;</span><span style="color: #000088;">$receiver</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$invoker</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Invoker<span style="color: #009900;">&#40;</span><span style="color: #000088;">$command</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$invoker</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">action</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
Client<span style="color: #339933;">::</span><span style="color: #004000;">main</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p><strong>【命令模式协作】</strong><br />
1、Client创建一个ConcreteCommand对象并指定它的Receiver对象<br />
2、某Invoker对象存储该ConcreteCommand对象<br />
3、该Invoker通过调用Command对象的execute操作来提交一个请求。若该命令是可撤消的，ConcreteCommand就在执行execute操作之前存储当前状态以用于取消命令。<br />
4、ConcreteCommand对象对调用它的Receiver的一些操作以执行该请求。</p>
<p><strong>【宏命令】</strong><br />
在这里，我们以一个简单的增加和粘贴功能为例，将这两个命令组成一个宏命令。<br />
我们可以新建复制命令和粘贴命令，然后将其添加到宏命令中去。<br />
如下所示代码：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #009933; font-style: italic;">/**
 * 命令模式之宏命令 2010-08-22 00:10  sz
 * @author phppan.p#gmail.com  http://www.phppan.com                                                   
 * 哥学社成员（http://www.blog-brother.com/）
 * @package design pattern
 */</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 命令角色
 */</span>
<span style="color: #000000; font-weight: bold;">interface</span> Command <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 执行方法
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> execute<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 宏命令接口
 */</span>
<span style="color: #000000; font-weight: bold;">interface</span> MacroCommand <span style="color: #000000; font-weight: bold;">extends</span> Command <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     *  宏命令聚集的管理方法，可以删除一个成员命令
     * @param Command $command
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> remove<span style="color: #009900;">&#40;</span>Command <span style="color: #000088;">$command</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 宏命令聚集的管理方法，可以增加一个成员命令
     * @param Command $command
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> add<span style="color: #009900;">&#40;</span>Command <span style="color: #000088;">$command</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> DemoMacroCommand implements MacroCommand <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_commandList</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_commandList <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> remove<span style="color: #009900;">&#40;</span>Command <span style="color: #000088;">$command</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$key</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_search</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$command</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_commandList<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$key</span> <span style="color: #339933;">===</span> <span style="color: #009900; font-weight: bold;">FALSE</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">FALSE</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_commandList<span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> add<span style="color: #009900;">&#40;</span>Command <span style="color: #000088;">$command</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #990000;">array_push</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_commandList<span style="color: #339933;">,</span> <span style="color: #000088;">$command</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> execute<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_commandList <span style="color: #b1b100;">as</span> <span style="color: #000088;">$command</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$command</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 具体拷贝命令角色
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> CopyCommand implements Command <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_receiver</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span>Receiver <span style="color: #000088;">$receiver</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_receiver <span style="color: #339933;">=</span> <span style="color: #000088;">$receiver</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 执行方法
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> execute<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_receiver<span style="color: #339933;">-&gt;</span><span style="color: #990000;">copy</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 具体拷贝命令角色
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> PasteCommand implements Command <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_receiver</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span>Receiver <span style="color: #000088;">$receiver</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_receiver <span style="color: #339933;">=</span> <span style="color: #000088;">$receiver</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 执行方法
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> execute<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_receiver<span style="color: #339933;">-&gt;</span><span style="color: #004000;">paste</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 接收者角色
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Receiver <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">/* 接收者名称 */</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_name</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_name <span style="color: #339933;">=</span> <span style="color: #000088;">$name</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 复制方法
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #990000;">copy</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_name<span style="color: #339933;">,</span> <span style="color: #0000ff;">' do copy action.&lt;br /&gt;'</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 粘贴方法
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> paste<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_name<span style="color: #339933;">,</span> <span style="color: #0000ff;">' do paste action.&lt;br /&gt;'</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 请求者角色
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Invoker <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_command</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span>Command <span style="color: #000088;">$command</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_command <span style="color: #339933;">=</span> <span style="color: #000088;">$command</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> action<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_command<span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 客户端
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Client <span style="color: #009900;">&#123;</span>
&nbsp;
     <span style="color: #009933; font-style: italic;">/**
     * Main program.
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$receiver</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Receiver<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'phpppan'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$pasteCommand</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> PasteCommand<span style="color: #009900;">&#40;</span><span style="color: #000088;">$receiver</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$copyCommand</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> CopyCommand<span style="color: #009900;">&#40;</span><span style="color: #000088;">$receiver</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$macroCommand</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> DemoMacroCommand<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$macroCommand</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$copyCommand</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$macroCommand</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$pasteCommand</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$invoker</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Invoker<span style="color: #009900;">&#40;</span><span style="color: #000088;">$macroCommand</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$invoker</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">action</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$macroCommand</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">remove</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$copyCommand</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$invoker</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Invoker<span style="color: #009900;">&#40;</span><span style="color: #000088;">$macroCommand</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$invoker</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">action</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
Client<span style="color: #339933;">::</span><span style="color: #004000;">main</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>个人觉得在命令的委派操作上，与<a href="http://www.phppan.com/2010/05/php-design-pattern-1-visitor/">访问者模式(Visitor模式)</a>有相似之处。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/08/php-design-pattern-15-comman/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP设计模式笔记：使用PHP实现合成模式</title>
		<link>https://www.phppan.com/2010/08/php-design-pattern-14-composite/</link>
		<comments>https://www.phppan.com/2010/08/php-design-pattern-14-composite/#comments</comments>
		<pubDate>Wed, 11 Aug 2010 01:08:44 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[设计模式]]></category>
		<category><![CDATA[读书总结]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=886</guid>
		<description><![CDATA[PHP设计模式笔记：使用PHP实现合成模式 【意图】 将对象组合成树形结构以表示&#8221;部分-整体&#8 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP设计模式笔记：使用PHP实现合成模式</p>
<p><strong>【意图】</strong><br />
将对象组合成树形结构以表示&#8221;部分-整体&#8221;的层次结构。Composite使用户对单个对象和组合对象的使用具有一致性。<br />
Composite变化的是一个对象的结构和组成</p>
<p><strong>【合成模式中主要角色】</strong><br />
抽象组件(Component)角色：抽象角色，给参加组合的对象规定一个接口。在适当的情况下，实现所有类共有接口的缺省行为。声明一个接口用于访问和管理Component的子组件<br />
树叶组件(Leaf)角色：在组合中表示叶节点对象，叶节点没有子节点。在组合中定义图元对象的行为。<br />
树枝组件(Composite)角色：存储子部件。定义有子部件的那些部件的行为。在Component接口中实现与子部件有关的操作。<br />
客户端(Client)：通过Component接口操纵组合部件的对象</p>
<p><strong>【合成模式的优点和缺点】</strong><br />
Composite模式的优点<br />
1、简化客户代码<br />
2、使得更容易增加新类型的组件</p>
<p>Composite模式的缺点：使你的设计变得更加一般化，容易增加组件也会产生一些问题，那就是很难限制组合中的组件</p>
<p><strong>【合成模式适用场景】</strong><br />
1、你想表示对象的部分-整体层次结构<br />
2、你希望用户忽略组合对象和单个对象的不同，用户将统一地使用组合结构中的所有对象。</p>
<p><strong>【合成模式与其它模式】</strong><br />
<a href="http://www.phppan.com/2010/06/php-design-pattern-4-decorator/">装饰器模式</a>：Decorator模式经常与Composite模式一起使用。当装饰与合成一起使用时，它们通常有一个公共的父类。因此装饰必须支持具有add,remove和getChild操作的Component接口<br />
<a href="http://www.phppan.com/2010/08/php-design-pattern-13-flyweight/">享元模式</a>：Flyweight模式让你共享组件，但不再引用他们的父部件<br />
迭代器模式：Itertor可用来遍历Composite<br />
<a href="http://www.phppan.com/2010/05/php-design-pattern-1-visitor/">访问者模式</a>：Visitor将本来应该分布在Composite和Leaf类中的操作和行为局部化。</p>
<p><strong>【安全式的合成模式】</strong><br />
在Composite类里面声明所有的用来管理子类对象的方法。这样的做法是安全的。因为树叶类型的对象根本就没有管理子类的方法，因此，如果客户端对树叶类对象使用这些方法时，程序会在编译时期出错。编译通不过，就不会出现运行时期错误<br />
这样的缺点是不够透明，因为树叶类和合成类将具有不同的接口。</p>
<p><strong>【安全式的合成模式结构图】</strong><br />
<div id="attachment_887" style="width: 441px" class="wp-caption aligncenter"><a href="http://www.phppan.com/wp-content/uploads/2010/08/Composite.jpg"><img src="http://www.phppan.com/wp-content/uploads/2010/08/Composite.jpg" alt="安全式的合成模式" title="Composite 安全式的合成模式" width="431" height="304" class="size-full wp-image-887" /></a><p class="wp-caption-text">安全式的合成模式</p></div><br />
<strong>【安全式的合成模式PHP示例】</strong></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 安全的合成模式的PHP实现 2010-08-10 sz
 * @author 胖子 phppan.p#gmail.com  http://www.phppan.com                                        
 * 哥学社成员（http://www.blog-brother.com/）
 * @package design pattern
 */</span>
&nbsp;
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 抽象组件角色
 */</span>
<span style="color: #000000; font-weight: bold;">interface</span> Component <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 返回自己的实例
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getComposite<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 示例方法
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> operation<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 树枝组件角色
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Composite implements Component <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_composites</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_composites <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getComposite<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 示例方法，调用各个子对象的operation方法
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> operation<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'Composite operation begin:&lt;br /&gt;'</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_composites <span style="color: #b1b100;">as</span> <span style="color: #000088;">$composite</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$composite</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">operation</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'Composite operation end:&lt;br /&gt;&lt;br /&gt;'</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 聚集管理方法 添加一个子对象
     * @param Component $component  子对象
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> add<span style="color: #009900;">&#40;</span>Component <span style="color: #000088;">$component</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_composites<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$component</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 聚集管理方法 删除一个子对象
     * @param Component $component  子对象
     * @return boolean  删除是否成功
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> remove<span style="color: #009900;">&#40;</span>Component <span style="color: #000088;">$component</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_composites <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$row</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$component</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$row</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_composites<span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">FALSE</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 聚集管理方法 返回所有的子对象
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getChild<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
       <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_composites<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> Leaf implements Component <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_name</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_name <span style="color: #339933;">=</span> <span style="color: #000088;">$name</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> operation<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'Leaf operation '</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_name<span style="color: #339933;">,</span> <span style="color: #0000ff;">'&lt;br /&gt;'</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getComposite<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 客户端
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Client <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Main program.
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$leaf1</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Leaf<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'first'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$leaf2</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Leaf<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'second'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$composite</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Composite<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$composite</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$leaf1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$composite</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$leaf2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$composite</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">operation</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$composite</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">remove</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$leaf2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$composite</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">operation</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
Client<span style="color: #339933;">::</span><span style="color: #004000;">main</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p><strong>【透明式的合成模式】</strong><br />
在Composite类里面声明所有的用来管理子类对象的方法。这样做的是好处是所有的组件类都有相同的接口。在客户端看来，树叶类和合成类对象的区别起码在接口层次上消失了，客户端可以同等的对待所有的对象。这就是透明形式的合成模式<br />
缺点就是不够安全，因为树叶类对象和合成类对象在本质上是有区别的。树叶类对象不可能有下一个层次的对象，因此调用其添加或删除方法就没有意义了，这在编译期间是不会出错的，而只会在运行时期才会出错。</p>
<p><strong>【透明式的合成模式结构图】</strong><br />
<div id="attachment_888" style="width: 404px" class="wp-caption aligncenter"><a href="http://www.phppan.com/wp-content/uploads/2010/08/Composite2.jpg"><img src="http://www.phppan.com/wp-content/uploads/2010/08/Composite2.jpg" alt="透明式的合成模式" title="Composite2 透明式的合成模式" width="394" height="241" class="size-full wp-image-888" /></a><p class="wp-caption-text">透明式的合成模式</p></div></p>
<p><strong>【透明式的合成模式PHP示例】</strong></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 透明的合成模式的PHP实现 2010-08-10 sz
 * @author 胖子 phppan.p#gmail.com  http://www.phppan.com                                               
 * 哥学社成员（http://www.blog-brother.com/）
 * @package design pattern
 */</span>
&nbsp;
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 抽象组件角色
 */</span>
<span style="color: #000000; font-weight: bold;">interface</span> Component <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 返回自己的实例
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getComposite<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 示例方法
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> operation<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #009933; font-style: italic;">/**
     * 聚集管理方法 添加一个子对象
     * @param Component $component  子对象
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> add<span style="color: #009900;">&#40;</span>Component <span style="color: #000088;">$component</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 聚集管理方法 删除一个子对象
     * @param Component $component  子对象
     * @return boolean  删除是否成功
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> remove<span style="color: #009900;">&#40;</span>Component <span style="color: #000088;">$component</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 聚集管理方法 返回所有的子对象
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getChild<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 树枝组件角色
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Composite implements Component <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_composites</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_composites <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getComposite<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 示例方法，调用各个子对象的operation方法
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> operation<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'Composite operation begin:&lt;br /&gt;'</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_composites <span style="color: #b1b100;">as</span> <span style="color: #000088;">$composite</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$composite</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">operation</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'Composite operation end:&lt;br /&gt;&lt;br /&gt;'</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 聚集管理方法 添加一个子对象
     * @param Component $component  子对象
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> add<span style="color: #009900;">&#40;</span>Component <span style="color: #000088;">$component</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_composites<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$component</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 聚集管理方法 删除一个子对象
     * @param Component $component  子对象
     * @return boolean  删除是否成功
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> remove<span style="color: #009900;">&#40;</span>Component <span style="color: #000088;">$component</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_composites <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$row</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$component</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$row</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_composites<span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">FALSE</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 聚集管理方法 返回所有的子对象
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getChild<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
       <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_composites<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> Leaf implements Component <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_name</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_name <span style="color: #339933;">=</span> <span style="color: #000088;">$name</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> operation<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'Leaf operation '</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_name<span style="color: #339933;">,</span> <span style="color: #0000ff;">'&lt;br /&gt;'</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getComposite<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
      <span style="color: #009933; font-style: italic;">/**
     * 聚集管理方法 添加一个子对象,此处没有具体实现，仅返回一个FALSE
     * @param Component $component  子对象
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> add<span style="color: #009900;">&#40;</span>Component <span style="color: #000088;">$component</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">FALSE</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 聚集管理方法 删除一个子对象
     * @param Component $component  子对象
     * @return boolean  此处没有具体实现，仅返回一个FALSE
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> remove<span style="color: #009900;">&#40;</span>Component <span style="color: #000088;">$component</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">FALSE</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 聚集管理方法 返回所有的子对象 此处没有具体实现，返回null
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getChild<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
       <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 客户端
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Client <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Main program.
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$leaf1</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Leaf<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'first'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$leaf2</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Leaf<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'second'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$composite</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Composite<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$composite</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$leaf1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$composite</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$leaf2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$composite</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">operation</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$composite</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">remove</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$leaf2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$composite</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">operation</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
Client<span style="color: #339933;">::</span><span style="color: #004000;">main</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>可以看到透明式合成模式的Leaf有各聚集管理方法的平庸实现</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/08/php-design-pattern-14-composite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
