小觋哥 發表於 2019-7-9 16:21:00

PHP实现单例模式

<p>单例模式的定义:保证一个类<strong>只有一个</strong>实例,并提供一个访问它的全局访问点。</p>
<p>PHP实现单例模式:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Singleton
{
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">创建静态私有的变量保存该类对象</span>
    <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(128, 0, 128, 1)">$instance</span><span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">防止使用new直接创建对象</span>
    <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> __construct(){}

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">防止使用clone克隆对象</span>
    <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> __clone(){}

    </span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> getInstance()
    {
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">判断$instance是否是Singleton的对象,不是则创建</span>
      <span style="color: rgba(0, 0, 255, 1)">if</span> (!self::<span style="color: rgba(128, 0, 128, 1)">$instance</span><span style="color: rgba(0, 0, 0, 1)"> instanceof self) {
            self</span>::<span style="color: rgba(128, 0, 128, 1)">$instance</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> self();
      }
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> self::<span style="color: rgba(128, 0, 128, 1)">$instance</span><span style="color: rgba(0, 0, 0, 1)">;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> test()
    {
      </span><span style="color: rgba(0, 0, 255, 1)">echo</span> "我是一个单例模式"<span style="color: rgba(0, 0, 0, 1)">;
    }
}

</span><span style="color: rgba(128, 0, 128, 1)">$sing</span> = Singleton::<span style="color: rgba(0, 0, 0, 1)">getInstance();
</span><span style="color: rgba(128, 0, 128, 1)">$sing</span>-&gt;<span style="color: rgba(0, 0, 0, 1)">test();
</span><span style="color: rgba(128, 0, 128, 1)">$sing2</span> = <span style="color: rgba(0, 0, 255, 1)">new</span> Singleton(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Fatal error: Uncaught Error: Call to private Singleton::__construct() from invalid context in</span>
<span style="color: rgba(128, 0, 128, 1)">$sing3</span> = <span style="color: rgba(0, 0, 255, 1)">clone</span> <span style="color: rgba(128, 0, 128, 1)">$sing</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Fatal error: Uncaught Error: Call to private Singleton::__clone() from context</span></pre>
</div>
<p>&nbsp;</p>
<p>PHP实现单例模式有什么意义:</p>
<p><span style="font-size: 13px">没有意义,PHP没有线程概念,没有异步代码,不会常驻内存,所有的修改自己都可以控制,不需要保证类只有一个实例,有什么意义?你要在数据库连接类中使用单例模式,万一有的页面需要连接两个数据库怎么办?</span></p>
<p><span style="font-size: 13px">真的没有意义吗?</span></p>
<p><span style="font-size: 13px">当然不是。</span></p>
<p><span style="font-size: 13px">看下代码:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> A
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> show()
    {
      </span><span style="color: rgba(0, 0, 255, 1)">echo</span> "我是A类函数,要调用B类函数和C类函数&lt;br/&gt;"<span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(128, 0, 128, 1)">$b</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> B();
      </span><span style="color: rgba(128, 0, 128, 1)">$b</span>-&gt;<span style="color: rgba(0, 0, 0, 1)">show();
      </span><span style="color: rgba(128, 0, 128, 1)">$c</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> C();
      </span><span style="color: rgba(128, 0, 128, 1)">$c</span>-&gt;show('A'<span style="color: rgba(0, 0, 0, 1)">);
    }
}

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> B
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> show()
    {
      </span><span style="color: rgba(0, 0, 255, 1)">echo</span> "我是B类函数,要调用C类函数&lt;br/&gt;"<span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(128, 0, 128, 1)">$c</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> C();
      </span><span style="color: rgba(128, 0, 128, 1)">$c</span>-&gt;show('B'<span style="color: rgba(0, 0, 0, 1)">);
    }
}

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> C
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> show(<span style="color: rgba(128, 0, 128, 1)">$parm</span><span style="color: rgba(0, 0, 0, 1)">)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">echo</span> "我是C类函数,现在被{<span style="color: rgba(128, 0, 128, 1)">$parm</span>}类函数调用&lt;br/&gt;"<span style="color: rgba(0, 0, 0, 1)">;
    }
}

</span><span style="color: rgba(128, 0, 128, 1)">$a</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> A();
</span><span style="color: rgba(128, 0, 128, 1)">$a</span>-&gt;show();</pre>
</div>
<p>&nbsp;<span style="font-size: 15px">这里调用的过程中,创建了两个C类对象,我们知道,new是很耗资源的一种操作,如果这里C类是单例模式,只new一次就行了,这个想法是可以的,但我们一般用另外一种方法来做:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> A
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> show()
    {
      </span><span style="color: rgba(0, 0, 255, 1)">echo</span> "我是A类函数,要调用B类函数和C类函数&lt;br/&gt;"<span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(128, 0, 128, 1)">$b</span> = Unit::getInstance('B'<span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(128, 0, 128, 1)">$b</span>-&gt;<span style="color: rgba(0, 0, 0, 1)">show();
      </span><span style="color: rgba(128, 0, 128, 1)">$c</span> = Unit::getInstance('C'<span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(128, 0, 128, 1)">$c</span>-&gt;show('A'<span style="color: rgba(0, 0, 0, 1)">);
    }
}

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> B
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> show()
    {
      </span><span style="color: rgba(0, 0, 255, 1)">echo</span> "我是B类函数,要调用C类函数&lt;br/&gt;"<span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(128, 0, 128, 1)">$c</span> = Unit::getInstance('C'<span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(128, 0, 128, 1)">$c</span>-&gt;show('B'<span style="color: rgba(0, 0, 0, 1)">);
    }
}

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> C
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> __construct()
    {
      </span><span style="color: rgba(0, 0, 255, 1)">echo</span> "C类对象被创建&lt;br/&gt;"<span style="color: rgba(0, 0, 0, 1)">;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> show(<span style="color: rgba(128, 0, 128, 1)">$parm</span><span style="color: rgba(0, 0, 0, 1)">)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">echo</span> "我是C类函数,现在被{<span style="color: rgba(128, 0, 128, 1)">$parm</span>}类函数调用&lt;br/&gt;"<span style="color: rgba(0, 0, 0, 1)">;
    }
}

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Unit
{
    </span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> getInstance(<span style="color: rgba(128, 0, 128, 1)">$class</span><span style="color: rgba(0, 0, 0, 1)">)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(128, 0, 128, 1)">$arr</span> = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 255, 1)">isset</span>(<span style="color: rgba(128, 0, 128, 1)">$arr</span>[<span style="color: rgba(128, 0, 128, 1)">$class</span>]) || !<span style="color: rgba(128, 0, 128, 1)">$arr</span>[<span style="color: rgba(128, 0, 128, 1)">$class</span>] instanceof <span style="color: rgba(128, 0, 128, 1)">$class</span><span style="color: rgba(0, 0, 0, 1)">) {
            </span><span style="color: rgba(128, 0, 128, 1)">$arr</span>[<span style="color: rgba(128, 0, 128, 1)">$class</span>] = <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(128, 0, 128, 1)">$class</span><span style="color: rgba(0, 0, 0, 1)">();
      }
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 128, 1)">$arr</span>[<span style="color: rgba(128, 0, 128, 1)">$class</span><span style="color: rgba(0, 0, 0, 1)">];
    }
}

</span><span style="color: rgba(128, 0, 128, 1)">$a</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> A();
</span><span style="color: rgba(128, 0, 128, 1)">$a</span>-&gt;show();</pre>
</div>
<p><span style="font-size: 15px">执行代码可以看到,C类只被实例化了一次,再实际操作中,我们一般使用静态变量保存对象,变相实现单例模式。</span></p>
<p><strong><span style="font-size: 15px">单例模式和使用静态变量实现单例的区别:</span></strong></p>
<p><span style="font-size: 15px">单例模式强制类只能创建一个对象,一般是安全或者统一界面展示的时候会用到,而静态变量实现单例主要是为了减少new操作,并不能阻止new和clone操作。</span></p>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/shamohai/p/11158206.html
頁: [1]
查看完整版本: PHP实现单例模式