Miscellaneous
|
|
|
|
<?php
// singleton.php
//
// Class that can only have one instance of itself.
// Repeated attempt to create new objects will fail unless
// using the instance() interface in which case the same
// object will be used each time.
//
// This is a classic GOF pattern and follows that
// interface.
//
// Usage:
//
// To create a class that is a singleton...
//
// class MyClass extends Singleton {
//
// function MyClass(...) {
// $this->Singleton();
// ...
// }
//
// ...
//
// function &instance(...) {
// return Singleton::instance("MyClass", ...);
// }
// }
// The instance() method chaining is convenient, but unnecessary.
//
// To create a singleton object...
//
// $my1 = &MyClass::instance($my_params);
// $my2 = &Singleton::instance("MyClass", $my_params);
//
// If you cannot put Singleton behaviour in the
// inheritance tree, then you can achieve a partial
// guarding effect as follows...
//
// class MyClass extends Something {
// var $_guard;
//
// function MyClass(...) {
// $this->_guard = &new Singleton("MyClass");
// ...
// }
//
// ...
// }
//
// Author: Marcus Baker
// Created: 13/8/2001
// PHP Version: Tested 4.1, 4.12. Should work on 4.06 as well.
// Copyright: Public domain, no warranty what so ever.
//
// $Id$
//
// Revisions...
// 12/12/2001
// Rewritten for later versions of PHP.
// Registry library removed.
//
if (!defined("SINGLETON_INCLUDED")) {
define("SINGLETON_INCLUDED", "YES");
// Singleton class.
//
// Object that can only be instantiated once.
//
class Singleton {
var $_is_unique; // Should be true if singleton valid.
// Singleton->Singleton() protected
//
// Produces an error if the class already exists.
// Param:
// <string> $sClass Class name to be registered.
// Only necessary when using composition.
// Returns:
// <bool> TRUE if OK.
// Notes:
// When including a singleton as a member, the holding
// object class name must be passed to the constructor.
function Singleton($class = "") {
if ($class == "") {
$class = get_class($this);
}
$registry = &Singleton::_get_registry();
if (isset($registry[strtolower($class)])) { // Class already exists.
if (defined("SINGLETON_DUPLICATE_FATAL")) {
die("Attempt to create duplicate Singleton in class "".get_class($this).""");
}
trigger_error("Attempt to create duplicate Singleton in class "".get_class($this).""", E_USER_ERROR);
$this->_is_unique = false;
return;
}
$registry[strtolower($class)] = &$this; // Stash self in the registry.
$this->_is_unique = true;
}
// Singleton->instance() class public
//
// Creates or fetches the only instance
// allowed of the class.
// Param:
// <string> Class name.
// <...> Constructor args. for object.
// Returns:
// <singleton> Reference to new or existing object.
function &instance() {
// We need at least a class name in the arguments.
//
$args = func_get_args();
if (count($args) == 0) { // No class name.
trigger_error("Missing class name in Singleton::instance()", E_USER_ERROR);
return "";
}
// The class name should be valid.
//
$class = array_shift($args);
if (!is_string($class) || !class_exists($class)) { // Invalid class name.
trigger_error("Invalid class name in Singleton::instance()", E_USER_ERROR);
return "";
}
// Need to pass through other arguments to the new operator.
//
$arg_labels = array();
for ($i = 0; $i < count($args); $i++) {
$arg_labels[$i] = "$args[$i]";
}
$args_str = implode(", ", $arg_labels); // Arguments as code string.
// Check the singleton registry.
//
$registry = &Singleton::_get_registry();
if (isset($registry[strtolower($class)])) {
if (count($args) > 0) {
trigger_error("Cannot reinstantiate "$class" with new parameters in Singleton::instance()", E_USER_NOTICE);
}
return $registry[strtolower($class)];
}
// Create and register the new class.
//
eval("new $class($args_str);");
return $registry[strtolower($class)];
}
// Singleton->_get_registry() class private
//
// Closure for the list of all singletons.
// Param:
// None
// Returns:
// <hash> Reference to new or existing object.
function &_get_registry() {
static $_registry;
if (!isset($_registry)) {
$_registry = array();
}
return $_registry;
}
// Singleton->is_unique() public
//
// Accessor for state after construction.
// If true then this object is not the first one created.
// Param:
// None
// Returns:
// <hash> Reference to new or existing object.
function is_unique() {
return $this->_is_unique;
}
}
} ?>
|
|
|
Usage Example
|
|
|
Rate This Script
|
|
|
|