模式系列的开篇,首先介绍的是我最喜欢的单例模式(Singleton),简单而言,这属于:生成一个、且只生成一个对象实例的特殊类。segmentfault
这个惟一存在的类,将替代Global关键字,而且更安全。设计模式
全局变量是OOP程序猿遇到的主要BUG源泉之一,全局变量的冲突也是极其危险的,由于PHP不会对其产生任何级别的错误,若是结果不能直接观测,那么你的程序可能会让你感到懵圈。安全
尽管命名空间的出现,必定程度上的避免了全局冲突,然而,在空间内的冲突仍然可能存在。可全部的类均可以访问它,全局变量还是巨大的诱惑。测试
良好设计的系统:经过方法调用传递对象实例。this
每一个类都会与背景环境保持独立,并经过清晰的通讯方式,与系统中其它部分进行无耦合协做。spa
但有时,你不得不经过 中间件 来沟通各个组件,中间件会致使依赖、耦合,而且,假若组件返回的参数之一,包含了这个中间件,将会致使“依赖污染”。设计
怎样的中间件才能避免上述状况呢?调试
如同Global,它能够被全部对象使用;code
不存储在全局变量中,不接受覆写;面向对象设计模式
它在整个系统中,是惟一的。
为了解决这个问题,咱们能够强行控制“对象实例化”,咱们经过简单地定义一个私有构造方法,建立一个没法从外部实例化的类,经过静态方法与静态属性,来间接实例化它:
class Preferences { private $props = array(); private static $instance; private function __construct() { } public static function getInstance() { if (empty(self::$instance)) { self::$instance = new Preferences(); } return self::$instance; } public function setProperty($key, $val) { $this->props[$key] = $val; } public function getProperty($key) { return $this->props[$key]; } }
单例类建立完毕后,咱们进行测试:
// 设置属性 $pref = Preferences::getInstance(); $pref->setProperty("name", "UiTest"); unset($pref); // 调用属性 $pref2 = Preferences::getInstance(); echo $pref2->getProperty("name");
最终能够获得输出:UiTest,而且,你能够去设置任何值,来测试它的可用性。
最后附赠一张UML图:
(感谢云绘图软件:ProcessOn)
Bad Result:单例与全局变量都会:建立难以调试的依赖关系、被误用、绕过安全的通讯接口,因此,须要谨慎当心的部署单例类。
Nice Result:与全局变量不一样,单例的任何错误与冲突,都将以报错的形式出现(除非你关闭了错误提示),这下,你就能够放心的使用它了。