Конструктор является частным. Класс Singleton представляет собой одну из ситуаций, когда имеет смысл использовать частный конструктор. Частный конструктор не позволяет пользователям непосредственно реализовывать класс. Для этого они должны использовать метод getlnstance. Попытка реализовать класс с помощью оператора $obj = new Singleton приведет к фатальной ошибке, так как из глобального диапазона нельзя вызывать частный конструктор.
Одним из реальных примеров использования класса Singleton является класс конфигурации, который представляет собой оболочку для настроек приложения. В листинге 29.1 приведен простой пример. Благодаря типовому проекту Singleton в памяти никогда не будет больше одной копии конфигурационного файла. Любые изменения в конфигурации сохраняются автоматически.

Листинг 29.1. Настройка проекта Singleton

<?php /*
** конфигурационный файл singleton
*/
class Configuration class Singleton {
static private $instance = NULL; private function __construct()
{
...по мере необходимости провести инициализациюTM
}
static public function getInstance()
{
if (self::$instance == NULL)

{

 self::$instance = new Singleton(); 
}

return self::$instance;
}
. class logic goes here .
} {
static private $instance = NULL; private $ini_settings; private $updated = FALSE;
const INI_FILENAME = "/tmp/corephp.ini"; private function __construct()
{
if(file_exists(self::INI_FILENAME))
{
$this->ini_settings = parse_ini_file(self::INI_FILENAME);
}
}
private function __destruct()
{
//если конфигурация не претерпела изменения, //то нет необходимости менять ее на диске if(!$this->updated)
{
return;
}
// переписать в файл INI версию из памяти $fp = fopen(self::INI_FILENAME, "w");
if(!$fp)
{
return;
}
foreach ($this->ini_settings as $key => $value)
{
fputs($fp, "$key = "$value"n");
}
fclose($fp);
}
public function getInstance()
{
if(self::$instance == NULL)
{
self::$instance = new Configuration();
}
return self::$instance;
}
public function get($name)
{
if(isset($this->ini_settings[$name]))
{
return $this->ini_settings[$name];
}
else
{
return(NULL);

 } 
}

public function set($name, $value)
{
//модифицировать только в случае отличия от //того, что есть
if(!isset($this->ini_settings[$name]) OR
($this->ini_settings[$name] != $value))
{
$this->ini_settings[$name] = $value; $this->updated = TRUE;
}
}
}
//Протестировать класс
$config = Configuration::getInstance(); $config->set("username", "leon"); $config->set("password", "secret"); print($config->get("username"));
?>

29.3. Проект Factory
Проект Factory представляет собой типовой проект, предназначенный для разделения реализации объектов от прикладного кода, использующего их в своей работе. Например, можно использовать различные типы объектов в зависимости от ситуации. Если существуют два визуализирующих класса, HtmlRenderer и WmlRenderer, и необходимо прозрачным образом использовать необходимый класс в зависимости от подключенного клиента, то лучше всего воспользоваться типовым проектом Factory.
Существует множество различных вариантов типового проекта Factory. На рис. 29.2 показан простейший вариант, в котором используются глобальные функции.
Метод Factory не принимает никаких аргументов, но во многих ситуациях может потребоваться передать информацию этому методу, чтобы он определил, какой тип объекта необходимо реализовать. Ничто в типовом проекте не препятствует передать аргументы конструктору в типовом проекте Factory.
Довольно популярным случаем при реализации метода Factory является реализация преобразующего кода, принимающего двухмерный трансформированный поток и преобразующего его в объекты.
Каким образом можно создать обобщенный код с возможностью реализовать объект любого типа, который может встретиться в потоке? Что если необходимо задать конструктору различные аргументы, зависящие от типа объекта, который реализуется? Реализация такого класса представлена в листинге 29.2.
Типовые проекты
Листинг 29.2. Зарегистрированные классы для типового проекта Factory

<?php
class Factory
{
private $registeredClasses = array(); static private $instance = NULL; private function __construct() {} static function getInstance()
{
if(self::$instance == NULL)
{
self::$instance = new Factory();
}
return self::$instance;
}
function registerClass($id, $creator_func)
{
$this->registeredClasses[$id] = $creator_func;
}
function createObject($id, $args)
{
if(!isset($this->registeredClasses[$id]))
{
return(NULL);
}
return($this->registeredClasses[$id]($args));
}
}
class MyClass
{
private $created;
public function __construct()
{
$created = time();
}
public function getCreated()
{
return($this->created);
}
}
function MyClassCreator()
{
return(new MyClass());
}
$factory = Factory::getInstance(); $factory->registerClass(1234, "MyClassCreator"); $instance = $factory->createObject(1234, array());
?>

 Читатель, знакомый со всеми нюансами синтаксиса PHP, знает, что существует простейший способ это сделать. В листинге 29.2 продемонстрирован более объектно-ориентированный метод решения проблемы, который был реализован на других языках. Он также имеет определенную гибкость, позволяющую реализовать дополнительную логику при создании (возможно, отправляя определенную информацию кон­структору). На практике точнее будет сказать, что PHP имеет встроенную поддержку для метода Factory, реализуемую простым оператором $object = new $classname.