当前位置: 首页 > 图文教程 > 网络编程 > PHP > 在PHP中使用全局变量【二】
使用单件(Singletons)
解决函数参数问题的一种方法就是采用单件(Singletons)来代替函数参数。单件是一类特殊的对象,它们只能实例化一次,而且含有一个静态方法来返回对象的接口。下面的例子演示了如何构建一个简单的单件:
| 以下为引用的内容: <?php // Get instance of DBConnection $db =& DBConnection::getInstance(); // Set user property on object $db->user = 'sa'; // Set second variable (which points to the same instance) $second =& DBConnection::getInstance(); // Should print 'sa' echo $second->user; Class DBConnection { var $user; function &getInstance() { static $me; if (is_object($me) == true) { return $me; } $me = new DBConnection; return $me; } function connect() { // TODO } function query() { // TODO } } ?>
|
| 以下为引用的内容: <?php function test() { $db = DBConnection::getInstance(); // Do something with the object } ?> |
注册模式
让一些对象能够被我们代码中所有的组件使用到(译者注:全局化对象或者数据)的最好的方法就是使用一个中央容器对象,用它来包含我们所有的对象。通常这种容器对象被人们称为一个注册器。它非常的灵活而且也非常的简单。一个简单的注册器对象就如下所示:
| 以下为引用的内容: <?php Class Registry { var $_objects = array(); function set($name, &$object) { $this->_objects[$name] =& $object; } function &get($name) { return $this->_objects[$name]; } } ?> |
使用注册器对象的第一步就是使用方法set()来注册一个对象:
| 以下为引用的内容: <?php $db = new DBConnection; $settings = new Settings_XML; $user = new User; // Register objects $registry =& new Registry; $registry->set ('db', $db); $registry->set ('settings', $settings); $registry->set ('user', $user); ?> |
现在我们的寄存器对象容纳了我们所有的对象,我们指需要把这个注册器对象传递给一个函数(而不是分别传递三个对象)。看下面的例子:
| 以下为引用的内容: <?php function test(&$registry) { $db =& $registry->get('db'); $settings =& $registry->get('settings'); $user =& $registry->get('user'); // Do something with the objects } ?> |
为了更加容易的使用注册器,我们把它的调用改成单件模式(译者注:不使用前面提到的函数传递)。因为在我们的程序中只需要使用一个注册器,所以单件模式使非常适合这种任务的。在注册器类里面增加一个新的方法,如下所示:
| 以下为引用的内容: <? function &getInstance() { static $me; if (is_object($me) == true) { return $me; } $me = new Registry; return $me; } ?> |
这样它就可以作为一个单件来使用,比如:
| 以下为引用的内容: <?php $db = new DBConnection; $settings = new Settings_XML; $user = new User; // Register objects $registry =& Registry::getInstance(); $registry->set ('db', $db); $registry->set ('settings', $settings); $registry->set ('user', $user); function test() { $registry =& Registry::getInstance(); $db =& $registry->get('db'); $settings =& $registry->get('settings'); $user =& $registry->get('user'); // Do something with the objects } ?> |
请求封装器
虽然我们的注册器已经使“global”关键字完全多余了,在我们的代码中还是存在一种类型的全局变量:超级全局变量,比如变量$_POST,$_GET。虽然这些变量都非常标准,而且在你使用中也不会出什么问题,但是在某些情况下,你可能同样需要使用注册器来封装它们。
一个简单的解决方法就是写一个类来提供获取这些变量的接口。这通常被称为“请求封装器”,下面是一个简单的例子:
| 以下为引用的内容: <?php Class Request { var $_request = array(); function Request() { // Get request variables $this->_request = $_REQUEST; } function get($name) { return $this->_request[$name]; } } ?> |
上面的例子是一个简单的演示,当然在请求封装器(request wrapper)里面你还可以做很多其他的事情(比如:自动过滤数据,提供默认值等等)。
下面的代码演示了如何调用一个请求封装器:
正如你看到的,现在我们不再依靠任何全局变量了,而且我们完全让这些函数远离了全局变量。
结论
在本文中,我们演示了如何从根本上移除代码中的全局变量,而相应的用合适的函数和变量来替代。注册模式是我最喜欢的设计模式之一,因为它是非常的灵活,而且它能够防止你的代码变得一塌糊涂。
另外,我推荐使用函数参数而不是单件模式来传递注册器对象。虽然使用单件更加轻松,但是它可能会在以后出现一些问题,而且使用函数参数来传递也更加容易被人理解。
评论 (0) All