<?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%ae%be%e8%ae%a1%e6%a8%a1%e5%bc%8f/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.phppan.com</link>
	<description>SaaS SaaS架构 团队管理 技术管理 技术架构 PHP 内核 扩展 项目管理</description>
	<lastBuildDate>Sat, 04 Apr 2026 01:19:58 +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>代理模式(Proxy)和PHP的反射功能</title>
		<link>https://www.phppan.com/2011/10/php-design-pattern-proxy-and-reflection/</link>
		<comments>https://www.phppan.com/2011/10/php-design-pattern-proxy-and-reflection/#comments</comments>
		<pubDate>Mon, 31 Oct 2011 01:06:06 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[proxy]]></category>
		<category><![CDATA[Reflection]]></category>
		<category><![CDATA[代理模式]]></category>
		<category><![CDATA[设计模式]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1492</guid>
		<description><![CDATA[代理模式(Proxy)和PHP的反射功能 本文包括以下内容： 代理模式概述 代理模式常规示例 使用PHP的反射 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p style="text-indent: 2em;">代理模式(Proxy)和PHP的反射功能</p>
<p style="text-indent: 2em;">本文包括以下内容：</p>
<ul>
<li>代理模式概述</li>
<li>代理模式常规示例</li>
<li>使用PHP的反射功能实现多代理</li>
</ul>
<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> ：为其他对象提供一种代理以控制对这个对象的访问［GOF95］</p>
<p style="text-indent: 2em;">代理模式是对象的结构模式，代理模式给某一个对象提供一个代理对象，并由此代理对象控制对原代理对象的引用。代理模式不应该让用户感觉到代理的存在，所以代理对象和原对象的对外的调用接口是一致的。</p>
<p style="text-indent: 2em;">代理模式一般包括三个角色：</p>
<ul>
<li>抽象主题角色(Subject)：它的作用是统一接口。此角色定义了真实主题角色和代理主题角色共用的接口，这样就可以在使用真实主题角色的地方使用代理主题角色。</li>
<li>真实主题角色(RealSubject)：隐藏在代理角色后面的真实对象。</li>
<li>代理主题角色(ProxySubject)：它的作用是代理真实主题，在其内部保留了对真实主题角色的引用。它与真实主题角色都继承自抽象主题角色，保持接口的统一。它可以控制对真实主题的存取，并可能负责创建和删除真实对象。代理角色并不是简单的转发，通常在将调用传递给真实对象之前或之后执行某些操作，当然你也可以只是简单的转发。 与适配器模式相比：适配器模式是为了改变对象的接口，而代理模式并不能改变所代理对象的接口。</li>
</ul>
<p style="text-indent: 2em;">从以上三个角色我们可以得出一个简单的示例：</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: #cccccc; font-style: italic;">/**
 * 代理模式简单示例 2011-10-30 sz
 * @author phppan.p#gmail.com  http://www.phppan.com
 * @package design pattern
 */</span>

<span style="color: #cccccc; font-style: italic;">/**
 * 抽象主题角色
 */</span>
abstract <span style="color: #cc7833;">class</span> Subject <span style="color: #ffffff;">{</span>
    abstract <span style="color: #cc7833;">public</span> <span style="color: #cc7833;">function</span> action<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>
<span style="color: #ffffff;">}</span>

<span style="color: #cccccc; font-style: italic;">/**
 * 真实主题角色
 */</span>
<span style="color: #cc7833;">class</span> RealSubject <span style="color: #cc7833;">extends</span> Subject <span style="color: #ffffff;">{</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> action<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: #99ff00;">"action method in RealSubject&lt;br /&gt;<span>\r</span><span>\n</span>"</span><span style="color: #e0882f;">;</span>
    <span style="color: #ffffff;">}</span>

<span style="color: #ffffff;">}</span>

<span style="color: #cccccc; font-style: italic;">/**
 * 代理主题角色
 */</span>
<span style="color: #cc7833;">class</span> ProxySubject <span style="color: #cc7833;">extends</span> Subject <span style="color: #ffffff;">{</span>

    <span style="color: #cc7833;">private</span> <span style="color: #6d9cbe;">$_real_subject</span> <span style="color: #e0882f;">=</span> <span style="color: #cc7833;">NULL</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> action<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>_beforeAction<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>

        <span style="color: #ff8400;">if</span> <span style="color: #ffffff;">(</span><a style="color: #1299da; text-decoration: none;" href="http://www.php.net/is_null"><span style="color: #e2392d;">is_null</span></a><span style="color: #ffffff;">(</span><span style="color: #6d9cbe;">$this</span><span style="color: #e0882f;">-&gt;</span>_real_subject<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>_real_subject <span style="color: #e0882f;">=</span> <span style="color: #cc7833;">new</span> RealSubject<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>
        <span style="color: #ffffff;">}</span>

        <span style="color: #6d9cbe;">$this</span><span style="color: #e0882f;">-&gt;</span>_real_subject<span style="color: #e0882f;">-&gt;</span><span style="color: #ffffff;">action</span><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>

        <span style="color: #6d9cbe;">$this</span><span style="color: #e0882f;">-&gt;</span>_afterAction<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>
    <span style="color: #ffffff;">}</span>

    <span style="color: #cccccc; font-style: italic;">/**
     * 请求前的操作
     */</span>
    <span style="color: #cc7833;">private</span> <span style="color: #cc7833;">function</span> _beforeAction<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: #99ff00;">"Before action in ProxySubject&lt;br /&gt;<span>\r</span><span>\n</span>"</span><span style="color: #e0882f;">;</span>
    <span style="color: #ffffff;">}</span>

    <span style="color: #cccccc; font-style: italic;">/**
     * 请求后的操作
     */</span>
    <span style="color: #cc7833;">private</span> <span style="color: #cc7833;">function</span> _afterAction<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: #99ff00;">"After action in ProxySubject&lt;br /&gt;<span>\r</span><span>\n</span>"</span><span style="color: #e0882f;">;</span>
    <span style="color: #ffffff;">}</span>

<span style="color: #ffffff;">}</span>

<span style="color: #cccccc; font-style: italic;">/**
 * 客户端
 */</span>
<span style="color: #cc7833;">class</span> Client <span style="color: #ffffff;">{</span>

    <span style="color: #cc7833;">public</span> <a style="color: #1299da; text-decoration: none;" href="http://www.php.net/static"><span style="color: #e2392d;">static</span></a> <span style="color: #cc7833;">function</span> main<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
        <span style="color: #6d9cbe;">$subject</span> <span style="color: #e0882f;">=</span> <span style="color: #cc7833;">new</span> ProxySubject<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>
        <span style="color: #6d9cbe;">$subject</span><span style="color: #e0882f;">-&gt;</span><span style="color: #ffffff;">action</span><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>
    <span style="color: #ffffff;">}</span>
<span style="color: #ffffff;">}</span>

Client<span style="color: #e0882f;">::</span><span style="color: #ffffff;">main</span><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>
<span>?&gt;</span></pre>
<p style="text-indent: 2em;">以上的示例适用于代理模式为一个对象提供一个代理对象。当为多个对象提供代理对象时，是否我们需要创建多个代理对象呢？ 如此按这种实现确实是，但是我们也可以将一个代理对象给多个对象用，或者可以作为一个代理工厂，此时一个对象会保留多个对象的引用， 并且在执行操作时需要判断所代理的是哪个对象，那么此时这种判断如何进行呢？ 以多个instanceof判断对象的归属？但是这样，代理对象也必须知道真实对象的方法， 如果我们现在的需求是实现一个代理对象和真实对象的松耦合，但是在代理对象中，对于每个真实对象都有一个前置操作和后转操作， 也许我们可以使用反射，那么反射是什么呢？</p>
<p style="text-indent: 2em;"><strong>反射一般来说是指在程序执行过程中获取程序相关的信息或者修改程序信息。</strong> 如获取类、方法、函数等的详细信息，或删除类方法定义。ruby的反射功能实现了类、对象、常量、变更等的获取和修改，但是在PHP中只有获取功能而无修改。 在PHP中我们可以使用PHP5以后的<a style="color: #1299da; text-decoration: underline;" href="http://cn2.php.net/manual/zh/intro.reflection.php">Reflection扩展</a>， 此扩展是PHP的核心扩展，在PHP安装时就已经自动加载，它的作用是分析PHP程序， 导出或提取出关于类、方法、函数、属性、参数等的详细信息，包括注释。 在这里我们经常可以此扩展来实现对PHP程序内部关于类、方法等的信息检测，并做作出处理。</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;">&lt;?PHP</span>
<span style="color: #cccccc; font-style: italic;">/**
 * 使用反射实现代理工厂 2011-10-30 sz
 * @author phppan.p#gmail.com  http://www.phppan.com
 * @package design pattern
 */</span>

<span style="color: #cccccc; font-style: italic;">/**
 * 真实主题角色 A
 */</span>
final <span style="color: #cc7833;">class</span> RealSubjectA <span style="color: #ffffff;">{</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> actionA<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: #99ff00;">"actionA method in RealSubject A &lt;br /&gt;<span>\r</span><span>\n</span>"</span><span style="color: #e0882f;">;</span>
    <span style="color: #ffffff;">}</span>

<span style="color: #ffffff;">}</span>

<span style="color: #cccccc; font-style: italic;">/**
 * 真实主题角色 B
 */</span>
final <span style="color: #cc7833;">class</span> RealSubjectB <span style="color: #ffffff;">{</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> actionB<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: #99ff00;">"actionB method in RealSubject B &lt;br /&gt;<span>\r</span><span>\n</span>"</span><span style="color: #e0882f;">;</span>
    <span style="color: #ffffff;">}</span>

<span style="color: #ffffff;">}</span>

<span style="color: #cccccc; font-style: italic;">/**
 * 代理主题角色
 */</span>
final <span style="color: #cc7833;">class</span> ProxySubject <span style="color: #ffffff;">{</span>

    <span style="color: #cc7833;">private</span> <span style="color: #6d9cbe;">$_real_subjects</span> <span style="color: #e0882f;">=</span> <span style="color: #cc7833;">NULL</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>_real_subjects <span style="color: #e0882f;">=</span> <a style="color: #1299da; text-decoration: none;" href="http://www.php.net/array"><span style="color: #e2392d;">array</span></a><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>
    <span style="color: #ffffff;">}</span>

    <span style="color: #cccccc; font-style: italic;">/**
     * 动态添加真实主题
     * @param type $subject
     */</span>
    <span style="color: #cc7833;">public</span> <span style="color: #cc7833;">function</span> addSubject<span style="color: #ffffff;">(</span><span style="color: #6d9cbe;">$subject</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
        <span style="color: #6d9cbe;">$this</span><span style="color: #e0882f;">-&gt;</span>_real_subjects<span style="color: #ffffff;">[</span><span style="color: #ffffff;">]</span> <span style="color: #e0882f;">=</span> <span style="color: #6d9cbe;">$subject</span><span style="color: #e0882f;">;</span>
    <span style="color: #ffffff;">}</span>

    <span style="color: #cc7833;">public</span> <span style="color: #cc7833;">function</span> __call<span style="color: #ffffff;">(</span><span style="color: #6d9cbe;">$name</span><span style="color: #e0882f;">,</span> <span style="color: #6d9cbe;">$args</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
        <span style="color: #ff8400;">foreach</span> <span style="color: #ffffff;">(</span><span style="color: #6d9cbe;">$this</span><span style="color: #e0882f;">-&gt;</span>_real_subjects <span style="color: #ff8400;">as</span> <span style="color: #6d9cbe;">$real_subject</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>

            <span style="color: #bd48b3; font-style: italic;">/* 使用反射获取类及方法相关信息　 */</span>
            <span style="color: #6d9cbe;">$reflection</span> <span style="color: #e0882f;">=</span> <span style="color: #cc7833;">new</span> ReflectionClass<span style="color: #ffffff;">(</span><span style="color: #6d9cbe;">$real_subject</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>

            <span style="color: #bd48b3; font-style: italic;">/* 如果不存在此方法，下一元素 */</span>
            <span style="color: #ff8400;">if</span> <span style="color: #ffffff;">(</span><span style="color: #e0882f;">!</span><span style="color: #6d9cbe;">$reflection</span><span style="color: #e0882f;">-&gt;</span><span style="color: #ffffff;">hasMethod</span><span style="color: #ffffff;">(</span><span style="color: #6d9cbe;">$name</span><span style="color: #ffffff;">)</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
                <span style="color: #ff8400;">continue</span><span style="color: #e0882f;">;</span>
            <span style="color: #ffffff;">}</span>

            <span style="color: #6d9cbe;">$method</span> <span style="color: #e0882f;">=</span> <span style="color: #6d9cbe;">$reflection</span><span style="color: #e0882f;">-&gt;</span><span style="color: #ffffff;">getMethod</span><span style="color: #ffffff;">(</span><span style="color: #6d9cbe;">$name</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>

            <span style="color: #bd48b3; font-style: italic;">/* 判断方法是否为公用方法并且是否不为抽象方法 */</span>
            <span style="color: #ff8400;">if</span> <span style="color: #ffffff;">(</span><span style="color: #6d9cbe;">$method</span> <span style="color: #e0882f;">&amp;&amp;</span> <span style="color: #6d9cbe;">$method</span><span style="color: #e0882f;">-&gt;</span><span style="color: #ffffff;">isPublic</span><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span> <span style="color: #e0882f;">&amp;&amp;</span> <span style="color: #e0882f;">!</span><span style="color: #6d9cbe;">$method</span><span style="color: #e0882f;">-&gt;</span><span style="color: #ffffff;">isAbstract</span><span style="color: #ffffff;">(</span><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>_beforeAction<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>

                <span style="color: #6d9cbe;">$method</span><span style="color: #e0882f;">-&gt;</span><span style="color: #ffffff;">invoke</span><span style="color: #ffffff;">(</span><span style="color: #6d9cbe;">$real_subject</span><span style="color: #e0882f;">,</span> <span style="color: #6d9cbe;">$args</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>

                <span style="color: #6d9cbe;">$this</span><span style="color: #e0882f;">-&gt;</span>_afterAction<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>

                <span style="color: #ff8400;">break</span><span style="color: #e0882f;">;</span>
            <span style="color: #ffffff;">}</span>
        <span style="color: #ffffff;">}</span>
    <span style="color: #ffffff;">}</span>

    <span style="color: #cccccc; font-style: italic;">/**
     * 请求前的操作
     */</span>
    <span style="color: #cc7833;">private</span> <span style="color: #cc7833;">function</span> _beforeAction<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: #99ff00;">"Before action in ProxySubject&lt;br /&gt;<span>\r</span><span>\n</span>"</span><span style="color: #e0882f;">;</span>
    <span style="color: #ffffff;">}</span>

    <span style="color: #cccccc; font-style: italic;">/**
     * 请求后的操作
     */</span>
    <span style="color: #cc7833;">private</span> <span style="color: #cc7833;">function</span> _afterAction<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: #99ff00;">"After action in ProxySubject&lt;br /&gt;<span>\r</span><span>\n</span>"</span><span style="color: #e0882f;">;</span>
    <span style="color: #ffffff;">}</span>

<span style="color: #ffffff;">}</span>

<span style="color: #cccccc; font-style: italic;">/**
 * 客户端
 */</span>
<span style="color: #cc7833;">class</span> Client <span style="color: #ffffff;">{</span>

    <span style="color: #cc7833;">public</span> <a style="color: #1299da; text-decoration: none;" href="http://www.php.net/static"><span style="color: #e2392d;">static</span></a> <span style="color: #cc7833;">function</span> main<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
        <span style="color: #6d9cbe;">$subject</span> <span style="color: #e0882f;">=</span> <span style="color: #cc7833;">new</span> ProxySubject<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>

        <span style="color: #6d9cbe;">$subject</span><span style="color: #e0882f;">-&gt;</span><span style="color: #ffffff;">addSubject</span><span style="color: #ffffff;">(</span><span style="color: #cc7833;">new</span> RealSubjectA<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>
        <span style="color: #6d9cbe;">$subject</span><span style="color: #e0882f;">-&gt;</span><span style="color: #ffffff;">addSubject</span><span style="color: #ffffff;">(</span><span style="color: #cc7833;">new</span> RealSubjectB<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>

        <span style="color: #6d9cbe;">$subject</span><span style="color: #e0882f;">-&gt;</span><span style="color: #ffffff;">actionA</span><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>
        <span style="color: #6d9cbe;">$subject</span><span style="color: #e0882f;">-&gt;</span><span style="color: #ffffff;">actionB</span><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>
    <span style="color: #ffffff;">}</span>

<span style="color: #ffffff;">}</span>

Client<span style="color: #e0882f;">::</span><span style="color: #ffffff;">main</span><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>
<span>?&gt;</span></pre>
<p style="text-indent: 2em;">以上示例使用反射机制实现了对不同真实对象的代理，但是还存在一些问题：</p>
<ul>
<li>对象的显式添加，不能对用户透明</li>
<li>真实对象的重复问题，如果存在多个相同的对象添加到对象列表中，如何处理？<a style="color: #1299da; text-decoration: underline;" href="http://www.phppan.com/2010/08/php-design-pattern-13-flyweight/">Flyweigh</a>?</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2011/10/php-design-pattern-proxy-and-reflection/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>面向模式的软件架构&#8211;分布式计算的模式语言读后感</title>
		<link>https://www.phppan.com/2011/04/pattern-oriented-software-architecutre/</link>
		<comments>https://www.phppan.com/2011/04/pattern-oriented-software-architecutre/#comments</comments>
		<pubDate>Wed, 27 Apr 2011 01:27:21 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[程序相关]]></category>
		<category><![CDATA[分布式]]></category>
		<category><![CDATA[设计模式]]></category>
		<category><![CDATA[读后感]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1347</guid>
		<description><![CDATA[数个早晨，捧着这本书，一个人 终于看完了，在痛苦中煎熬，回头望去，却不知所得。只看过GOF的23个模式及其它一 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p style="text-indent: 2em;">数个早晨，捧着这本书，一个人</p>
<p style="text-indent: 2em;">终于看完了，在痛苦中煎熬，回头望去，却不知所得。只看过GOF的23个模式及其它一些书籍中不成系统的介绍。 仰望这一望无际的模式，作者对模式信手拈来，娓娓而谈，不得不叹服。至此，不敢写总结，只能写读后感，权当慰藉。</p>
<p style="text-indent: 2em;">每种模式是记录了一个在特定环境下不断重复发生的问题以及相应的解决方案。 也许一种实现方法很常见，或者说已经用过，这是个人经验。 模式与个人经验相比：它被正式命名并记录，更有利于提炼、交流和分享架构层次上的知识。 本书一共介绍了114种模式，并且连接到其它文献中的介绍的150多种模式。 如此多的模式浓缩到这一本书中，确实页页都是精华。 读完整本书，以前的一些模糊性的内容被整理成模式语言的论述，如Layers、Pipes and Filters等等。 这些都有见过或用过，却不成系统。 由于接触分布式的内容较少，对于作者在分布式基础设施中提出的模式很难理解，待后续。 对于GOF的23种模式，作者按其主题分到了不同的章，每当遇到这些会有一种熟悉感，从而对其它模式的理解有一定的帮助作用。 但是读完本书后，觉得这23种模式处于一个基础或者说是实现层次位置。</p>
<p style="text-indent: 2em;">每章，作者列出主题和此主题中的问题，然后展示可以解决这些问题的模式，以及相关模式的关系。 对每个模式，作者列出此模式的相关模式，此模式的应用场景，此模式的意图和大概实现。</p>
<p style="text-indent: 2em;">对于这本书，我是直接从头到尾的通读，遇到不懂的模式去书上或网上查找，不懂的跳过，通读而已。 其它我们可以按主题阅读(按章阅读)或按模式阅读（按小节阅读）。 不过如果对模式了解不多，如我，还是老老实实从头到尾先看一遍吧，后面读第二遍再按主题和模式阅读吧。</p>
<p style="text-indent: 2em;">虽然有人反对模式，个人认为，存在即合理。模式将一些经验性的内容记录下来，值得推崇，却不可全按此来， 所有的解决方案都是基于特定问题的处理，虽然有通用的方案，却只能解决一些常见的问题，当我们遇到问题时，模式是一个很好的参考方案。 <strong>尽信书不如无书，若书未阅，何来信书之说？</strong></p>
<p style="text-indent: 2em;">现在，好读书，不求甚解，每有会意，欣然却不敢忘食。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2011/04/pattern-oriented-software-architecutre/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>
		<item>
		<title>PHP设计模式笔记：使用PHP实现享元模式</title>
		<link>https://www.phppan.com/2010/08/php-design-pattern-13-flyweight/</link>
		<comments>https://www.phppan.com/2010/08/php-design-pattern-13-flyweight/#comments</comments>
		<pubDate>Wed, 04 Aug 2010 01:06:58 +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=868</guid>
		<description><![CDATA[PHP设计模式笔记：使用PHP实现享元模式 【意图】 运用共享技术有效的支持大量细粒度的对象 享元模式变化的是 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP设计模式笔记：使用PHP实现享元模式</p>
<p><strong>【意图】</strong><br />
运用共享技术有效的支持大量细粒度的对象<br />
享元模式变化的是对象的存储开销</p>
<p><strong>【享元模式结构图】</strong><br />
<div id="attachment_870" style="width: 436px" class="wp-caption aligncenter"><a href="http://www.phppan.com/wp-content/uploads/2010/08/Flyweight.jpg"><img src="http://www.phppan.com/wp-content/uploads/2010/08/Flyweight.jpg" alt="享元模式" title="享元模式" width="426" height="266" class="size-full wp-image-870" /></a><p class="wp-caption-text">享元模式</p></div></p>
<p><strong>【享元模式中主要角色】</strong><br />
抽象享元(Flyweight)角色：此角色是所有的具体享元类的超类，为这些类规定出需要实现的公共接口。那些需要外蕴状态的操作可以通过调用商业以参数形式传入<br />
具体享元(ConcreteFlyweight)角色：实现Flyweight接口，并为内部状态（如果有的话）拉回存储空间。ConcreteFlyweight对象必须是可共享的。它所存储的状态必须是内部的<br />
不共享的具体享元（UnsharedConcreteFlyweight）角色：并非所有的Flyweight子类都需要被共享。Flyweigth使共享成为可能，但它并不强制共享。<br />
享元工厂(FlyweightFactory)角色：负责创建和管理享元角色。本角色必须保证享元对象可能被系统适当地共享<br />
客户端(Client)角色：本角色需要维护一个对所有享元对象的引用。本角色需要自行存储所有享元对象的外部状态</p>
<p><strong>【享元模式的优点和缺点】</strong><br />
享元模式的优点：Flyweight模式可以大幅度地降低内存中对象的数量。</p>
<p>享元模式的缺点：<br />
1、Flyweight模式使得系统更加复杂<br />
2、Flyweigth模式将享元对象的状态外部化，而读取外部状态使得运行时间稍微变长</p>
<p><strong>【享元模式适用场景】</strong><br />
当以下情况都成立时使用Flyweight模式：<br />
1、一个应用程序使用了大量的对象<br />
2、完全由于使用大量的对象，造成很大的存储开销<br />
3、对象的大多数状态都可变为外部状态<br />
4、如果删除对象的外部状态，那么可以用相对较少的共享对象取代很多组对象<br />
5、应用程序不依赖于对象标识。</p>
<p><strong>【享元模式与其它模式】</strong><br />
<a href="http://www.phppan.com/2010/06/php-design-pattern-6-singleton/">单例模式(Singleton)</a>：客户端要引用享元对象，是通过工厂对象创建或者获得的，客户端每次引用一个享元对象，都是可以通过同一个工厂对象来引用所需要的享元对象。因此，可以将享元工厂设计成单例模式，这样就可以保证客户端只引用一个工厂实例。因为所有的享元对象都是由一个工厂对象统一管理的，所以在客户端没有必要引用多个工厂对象。不管是单纯享元模式还是复合享元模式中的享元工厂角色，都可以设计成为单例模式，对于结果是不会有任何影响的。<br />
Composite模式：复合享元模式实际上是单纯享元模式与合成模式的组合。单纯享元对象可以作为树叶对象来讲，是可以共享的，而复合享元对象可以作为树枝对象，因此在复合享元角色中可以添加聚集管理方法。</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
</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;">/**
 * 享元模式的PHP简单实现 2010-08-03 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> Flyweight <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 示意性方法
     * @param string $state 外部状态
     */</span>
    <span style="color: #000000; font-weight: bold;">abstract</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: #000088;">$state</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> ConcreteFlyweight <span style="color: #000000; font-weight: bold;">extends</span> Flyweight <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_intrinsicState</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 构造方法
     * @param string $state  内部状态
     */</span>
    <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>_intrinsicState <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> operation<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: #b1b100;">echo</span> <span style="color: #0000ff;">'ConcreteFlyweight operation, Intrinsic State = '</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_intrinsicState
        <span style="color: #339933;">.</span> <span style="color: #0000ff;">' Extrinsic State = '</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$state</span> <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: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 不共享的具体享元，客户端直接调用
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> UnsharedConcreteFlyweight <span style="color: #000000; font-weight: bold;">extends</span> Flyweight <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_intrinsicState</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 构造方法
     * @param string $state  内部状态
     */</span>
    <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>_intrinsicState <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> operation<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: #b1b100;">echo</span> <span style="color: #0000ff;">'UnsharedConcreteFlyweight operation, Intrinsic State = '</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_intrinsicState
        <span style="color: #339933;">.</span> <span style="color: #0000ff;">' Extrinsic State = '</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$state</span> <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: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 享元工厂角色
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> FlyweightFactory <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_flyweights</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>_flyweights <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> getFlyweigth<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: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_flyweights<span style="color: #009900;">&#91;</span><span style="color: #000088;">$state</span><span style="color: #009900;">&#93;</span><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: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_flyweights<span style="color: #009900;">&#91;</span><span style="color: #000088;">$state</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</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>_flyweights<span style="color: #009900;">&#91;</span><span style="color: #000088;">$state</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ConcreteFlyweight<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>
    <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;">$flyweightFactory</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> FlyweightFactory<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$flyweight</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$flyweightFactory</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getFlyweigth</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'state A'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$flyweight</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">operation</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'other state A'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$flyweight</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$flyweightFactory</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getFlyweigth</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'state B'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$flyweight</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">operation</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'other state B'</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;">$uflyweight</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> UnsharedConcreteFlyweight<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'state A'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$uflyweight</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">operation</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'other state A'</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 />
复合享元模式对象是由一些单纯享元使用合成模式加以复合而成<br />
复合享元角色所代表的对象是不可以共享的，但是一个复合享元对象可以分解成为多个本身是单纯享元对象的组合。</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
</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;">/**
 * 复合享元模式的PHP简单实现 2010-08-03 sz
 * 《Java与模式》中的示意性源码的PHP修改版本
 * @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> Flyweight <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 示意性方法
     * @param string $state 外部状态
     */</span>
    <span style="color: #000000; font-weight: bold;">abstract</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: #000088;">$state</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> ConcreteFlyweight <span style="color: #000000; font-weight: bold;">extends</span> Flyweight <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_intrinsicState</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 构造方法
     * @param string $state  内部状态
     */</span>
    <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>_intrinsicState <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> operation<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: #b1b100;">echo</span> <span style="color: #0000ff;">'ConcreteFlyweight operation, Intrinsic State = '</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_intrinsicState
        <span style="color: #339933;">.</span> <span style="color: #0000ff;">' Extrinsic State = '</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$state</span> <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: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 不共享的具体享元，客户端直接调用
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> UnsharedConcreteFlyweight <span style="color: #000000; font-weight: bold;">extends</span> Flyweight <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_flyweights</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 构造方法
     * @param string $state  内部状态
     */</span>
    <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>_flyweights <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> operation<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: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_flyweights <span style="color: #b1b100;">as</span> <span style="color: #000088;">$flyweight</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$flyweight</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">operation</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>
    <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><span style="color: #000088;">$state</span><span style="color: #339933;">,</span> Flyweight <span style="color: #000088;">$flyweight</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>_flyweights<span style="color: #009900;">&#91;</span><span style="color: #000088;">$state</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$flyweight</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> FlyweightFactory <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_flyweights</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>_flyweights <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> getFlyweigth<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: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">is_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$state</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #666666; font-style: italic;">//  复合模式</span>
            <span style="color: #000088;">$uFlyweight</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> UnsharedConcreteFlyweight<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$state</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$row</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$uFlyweight</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$row</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getFlyweigth</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$row</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
            <span style="color: #b1b100;">return</span> <span style="color: #000088;">$uFlyweight</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">is_string</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$state</span><span style="color: #009900;">&#41;</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: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_flyweights<span style="color: #009900;">&#91;</span><span style="color: #000088;">$state</span><span style="color: #009900;">&#93;</span><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: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_flyweights<span style="color: #009900;">&#91;</span><span style="color: #000088;">$state</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</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>_flyweights<span style="color: #009900;">&#91;</span><span style="color: #000088;">$state</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ConcreteFlyweight<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>
        <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</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;
<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;">$flyweightFactory</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> FlyweightFactory<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$flyweight</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$flyweightFactory</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getFlyweigth</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'state A'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$flyweight</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">operation</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'other state A'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$flyweight</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$flyweightFactory</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getFlyweigth</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'state B'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$flyweight</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">operation</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'other state B'</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;">$uflyweight</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$flyweightFactory</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getFlyweigth</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'state A'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'state B'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$uflyweight</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">operation</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'other state A'</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>【PHP中享元模式的地位】</strong><br />
相对于其它模式，Flyweight模式在PHP的现有版本中没有太大的意义，因为PHP的生命周期是页面级的<br />
即从一个PHP文件执行开始会载入所需的资源，当执行完毕后，这些所有的资源会被全部释放。<br />
而一般来说我们也不会让一个页面执行太长时间。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/08/php-design-pattern-13-flyweight/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP设计模式笔记：使用PHP实现策略模式</title>
		<link>https://www.phppan.com/2010/07/php-design-pattern-12-strategy/</link>
		<comments>https://www.phppan.com/2010/07/php-design-pattern-12-strategy/#comments</comments>
		<pubDate>Wed, 28 Jul 2010 00:40:03 +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=850</guid>
		<description><![CDATA[PHP设计模式笔记：使用PHP实现策略模式 【意图】 定义一系列的算法，把它们一个个封装起来，并且使它们可相互 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP设计模式笔记：使用PHP实现策略模式</p>
<p><strong>【意图】</strong><br />
定义一系列的算法，把它们一个个封装起来，并且使它们可相互替换。策略模式可以使算法可独立于使用它的客户而变化<br />
策略模式变化的是算法</p>
<p><strong>【策略模式结构图】</strong><br />
<div id="attachment_851" style="width: 627px" class="wp-caption aligncenter"><a href="http://www.phppan.com/wp-content/uploads/2010/07/Strategy.jpg"><img src="http://www.phppan.com/wp-content/uploads/2010/07/Strategy.jpg" alt="策略模式" title="策略模式" width="617" height="155" class="size-full wp-image-851" /></a><p class="wp-caption-text">策略模式</p></div></p>
<p><strong>【策略模式中主要角色】</strong><br />
抽象策略(Strategy）角色：定义所有支持的算法的公共接口。通常是以一个接口或抽象来实现。Context使用这个接口来调用其ConcreteStrategy定义的算法<br />
具体策略(ConcreteStrategy)角色：以Strategy接口实现某具体算法<br />
环境(Context)角色：持有一个Strategy类的引用，用一个ConcreteStrategy对象来配置</p>
<p><strong>【策略模式的优点和缺点】</strong><br />
策略模式的优点：<br />
1、策略模式提供了管理相关的算法族的办法<br />
2、策略模式提供了可以替换继承关系的办法  将算封闭在独立的Strategy类中使得你可以独立于其Context改变它<br />
3、使用策略模式可以避免使用多重条件转移语句。</p>
<p>策略模式的缺点：<br />
1、客户必须了解所有的策略  这是策略模式一个潜在的缺点<br />
2、Strategy和Context之间的通信开销<br />
3、策略模式会造成很多的策略类</p>
<p><strong>【策略模式适用场景】</strong><br />
1、许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法<br />
2、需要使用一个算法的不同变体。<br />
3、算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的，与算法相关的数据结构<br />
4、一个类定义了多种行为，并且 这些行为在这个类的操作中以多个形式出现。将相关的条件分支移和它们各自的Strategy类中以代替这些条件语句</p>
<p><strong>【策略模式与其它模式】</strong><br />
Template模式：模板方法模式与策略模式的不同在于，策略模式使用委派的方法提供不同的算法行为，而模板方法使用继承的方法提供不同的算法行为<br />
<a href="http://www.phppan.com/2010/08/php-design-pattern-13-flyweight/">享元模式(flyweight模式)</a>：如果有多个客户端对象需要调用 同样的一睦策略类的话，就可以使它们实现享元模式</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;">&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #009933; font-style: italic;">/**
 * 策略模式的PHP简单实现 2010-07-25 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> Strategy <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> algorithmInterface<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;">/**
 * 具体策略角色A
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> ConcreteStrategyA implements Strategy <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> algorithmInterface<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;">'algorithmInterface A&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;">/**
 * 具体策略角色B
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> ConcreteStrategyB implements Strategy <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> algorithmInterface<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;">'algorithmInterface B&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;">/**
 * 具体策略角色C
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> ConcreteStrategyC implements Strategy <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> algorithmInterface<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;">'algorithmInterface C&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> Context <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">/* 引用的策略 */</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_strategy</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>Strategy <span style="color: #000088;">$strategy</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>_strategy <span style="color: #339933;">=</span> <span style="color: #000088;">$strategy</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> contextInterface<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>_strategy<span style="color: #339933;">-&gt;</span><span style="color: #004000;">algorithmInterface</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: #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;">$strategyA</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ConcreteStrategyA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$context</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Context<span style="color: #009900;">&#40;</span><span style="color: #000088;">$strategyA</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$context</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">contextInterface</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$strategyB</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ConcreteStrategyB<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$context</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Context<span style="color: #009900;">&#40;</span><span style="color: #000088;">$strategyB</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$context</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">contextInterface</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$strategyC</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ConcreteStrategyC<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$context</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Context<span style="color: #009900;">&#40;</span><span style="color: #000088;">$strategyC</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$context</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">contextInterface</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/07/php-design-pattern-12-strategy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP设计模式笔记：使用PHP实现状态模式</title>
		<link>https://www.phppan.com/2010/07/php-design-pattern-11-state/</link>
		<comments>https://www.phppan.com/2010/07/php-design-pattern-11-state/#comments</comments>
		<pubDate>Mon, 26 Jul 2010 00:59:48 +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=845</guid>
		<description><![CDATA[PHP设计模式笔记：使用PHP实现状态模式 【意图】 允许一个对象在其内部状态改变时改变它的行为。对象看起来似 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP设计模式笔记：使用PHP实现状态模式</p>
<p><strong>【意图】</strong><br />
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类<br />
状态模式变化的位置在于对象的状态</p>
<p><strong>【状态模式结构图】</strong><br />
<div id="attachment_847" style="width: 474px" class="wp-caption aligncenter"><a href="http://www.phppan.com/wp-content/uploads/2010/07/State.jpg"><img src="http://www.phppan.com/wp-content/uploads/2010/07/State.jpg" alt="状态模式" title="状态模式" width="464" height="153" class="size-full wp-image-847" /></a><p class="wp-caption-text">状态模式</p></div></p>
<p><strong>【状态模式中主要角色】</strong><br />
抽象状态(State)角色：定义一个接口，用以封装环境对象的一个特定的状态所对应的行为<br />
具体状态（ConcreteState)角色：每一个具体状态类都实现了环境（Context）的一个状态所对应的行为<br />
环境(Context)角色：定义客户端所感兴趣的接口，并且保留一个具体状态类的实例。这个具体状态类的实例给出此环境对象的现有状态</p>
<p><strong>【状态模式的优点和缺点】</strong><br />
1、它将与特定状态相关的行为局部化<br />
2、它使得状态转换显示化<br />
3、State对象可被共享</p>
<p><strong>【状态模式适用场景】</strong><br />
1、一个对象的行为取决于它的状态，并且它必须在运行时刻根据状态改变它的行为<br />
2、一个操作中含有庞大的多分支的条件语句，且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常，有多个操作包含这一相同的条件结构。State模式模式将每一个条件分支放入一个独立的类中。这使得你可以要所对象自身的情况将对象的状态作为一个对象，这一对象可以不依赖于其他对象而独立变化</p>
<p><strong>【状态模式与其它模式】</strong><br />
<a href="http://www.phppan.com/2010/06/php-design-pattern-6-singleton/">单例模式(singleton模式)</a>：具体状态对象通常是单例模式<br />
<a href="http://www.phppan.com/2010/08/php-design-pattern-13-flyweight/">享元模式(flyweight模式)</a>：享元模式解释了何时以及怎样共享状态对象</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
</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;">/**
 * 状态模式的PHP简单实现 2010-07-25 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> State <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> handle<span style="color: #009900;">&#40;</span>Context <span style="color: #000088;">$context</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;">/**
 * 具体状态角色A
 * 单例类
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> ConcreteStateA implements State <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">/* 唯一的实例 */</span>
    <span style="color: #000000; font-weight: bold;">private</span> static <span style="color: #000088;">$_instance</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</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>
&nbsp;
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 静态工厂方法，返还此类的唯一实例
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> getInstance<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: #990000;">is_null</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$_instance</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$_instance</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ConcreteStateA<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: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$_instance</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> handle<span style="color: #009900;">&#40;</span>Context <span style="color: #000088;">$context</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'Concrete Sate A handle method&lt;br /&gt;'</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$context</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setState</span><span style="color: #009900;">&#40;</span>ConcreteStateB<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</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: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * 具体状态角色B
 * 单例类
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> ConcreteStateB implements State <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">/* 唯一的实例 */</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> static <span style="color: #000088;">$_instance</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</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: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * 静态工厂方法，返还此类的唯一实例
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> getInstance<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: #990000;">is_null</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$_instance</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$_instance</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ConcreteStateB<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: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$_instance</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> handle<span style="color: #009900;">&#40;</span>Context <span style="color: #000088;">$context</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'Concrete Sate B handle method&lt;br /&gt;'</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$context</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setState</span><span style="color: #009900;">&#40;</span>ConcreteStateA<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</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: #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> Context <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: #009933; font-style: italic;">/**
     * 默认为StateA
     */</span>
    <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> ConcreteStateA<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</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>State <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> request<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;">-&gt;</span><span style="color: #004000;">handle</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</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: #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;">$context</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Context<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$context</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">request</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$context</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">request</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$context</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">request</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$context</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">request</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/07/php-design-pattern-11-state/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
