Registry or Singleton pattern in PHP?
我现在正在处理PHP类和对象。在这个问题中,字段和方法的名称是由它们组成的,这样您就可以了解我在说什么了。
它与使用单例和注册表设计模式有关。
现在假设我需要访问一个数据库对象、缓存对象、核心设置对象、会话对象,在我需要访问的几乎所有其他类中。所以我将使用一个注册表将所有4个对象存储到1个注册表类对象中。然后我可以轻松地将我的1个对象传递到任何其他需要访问这些对象的对象中。到目前为止这听起来不错,但是如果我有一些类不需要所有4个这些对象,如果我只需要访问数据库对象或者我的其他一些类中的会话对象呢?对于Perfromance,最好只在这些其他对象中使用一个单例,还是继续在这些对象中使用我的注册表?
我不太清楚这些对象在PHP中的工作方式,不知道是否会有任何形式的性能提升(内存使用率、CPU使用率、加载时间较短)。
因此,任何有这方面经验的人都可以告诉我,使用其中一个或另一个是否会有任何收获,我正处在一个阶段,我可以在不影响生产时间或任何事情的情况下走上另一条路。如果可以的话,我想用最好的方法。
您可以实现延迟加载以仅加载真正需要的对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | class Registry { private static $database = null; private static function connectDatabase($key) { [... do connection stuff ...] } public static function getDatabase($key) { if (Registry::$database == null) { Registry::connectDatabase($key); } return Registry::$database; } } |
注册数据库连接参数的代码留给读者作为练习。
这取决于你的申请。如果您仍然需要四个类中的三个,那么使用注册表比单独处理三个类更理想,因为您不需要第四个类。延迟加载类是减少内存占用的一种方法,但是您需要指示注册表何时创建对象,这与处理单例没有太大的不同。或者,您可以创建一个n参数的构造函数,或者使用一个数组来指示注册表在构造期间实例化哪些类。
1 2 3 4 5 6 7 8 9 10 11 | class Registry { public $class1; public $class2; function __construct($uses) { foreach($uses as $class) { $this->{$class} = new {$class}(); } } } |
然后通过指定要实例化的类来实例化注册表。
1 |
显然,您希望构造函数处理零个参数,以说明默认情况下实例化所有类。
也许这是正确的单例注册模式。OFC,您可以实现不同的东西,splFixedArray、arrayaccess接口和其他。此外,添加析构函数并销毁内部对象也不错,以确保不会发生泄漏。
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 | class oRegistry{ private static $instance = null; private $storage = array(); private function __construct(){} private function __clone(){} public static function getInstance(){ if( self::$instance === null ){ self::$instance = new self(); } return self::$instance; } public function attach($name, $o) { if( true === isset($this->storage[$name]) ) { throw new Exception('The instance with name '.$name.' already exists in registry.'); } if( !empty( $name ) ) { $this->storage[ $name ] = $o; } } public function detach( $name ){ if( isset( $this->storage[ $name ] ) ) { $this->storage[ $name ] = null; unset( $this->storage[ $name ] ); } } public function get( $name ){ if( false === isset( $this->storage[$name] ) ) { throw new Exception('Invalid instance requested'); } return $this->storage[ $name ]; } } // usage example $storage = oRegistry::getInstance(); $obj = new stdClass; $obj2 = new stdClass; $obj->test1 = 'test'; $obj2->test2 = 't2'; $storage->attach( 'test1', $obj ); $storage->attach( 'test2', $obj2 ); $got = $storage->get( 'test2' ); var_dump($got); // object(stdClass)#3 (1) { ["test2"]=> string(2)"t2" } $storage->detach( 'test2' ); $got = $storage->get( 'test2' ); var_dump($got); // bool(false) |