При использовании шаблонов, важно понимать их суть и целесообразность использования того или иного шаблона.
(Очень неплохое описание шаблонов citforum.ru/SE/project/pattern/index.shtml#toc)
1. Одиночка (Singleton)
Наверное это один из самых простых и понятных шаблонов. Суть которого заключается в создании\получении единственного экземпляра класса.
Где это может быть полезно? Очевидно, единственный экземпляр класса БД, кеширование, доступ к какому либо API (к примеру AdWords) и т.д.
Но пойдем немножко дальше и совместим "Одиночку" с шаблоном Factory (этакий гибрид). В классическом понимании, Factory, при каждом вызове создает новый экземпляр класса, но надо ли оно нам?
Необходимо отметить, что применени паттерна не означает невозможность создание нового экземпляра класса.
Непосредственно сам класс реализующий шаблон одиночки
PS: Decorator, Adpater .... coming soon
(Очень неплохое описание шаблонов citforum.ru/SE/project/pattern/index.shtml#toc)
1. Одиночка (Singleton)
Наверное это один из самых простых и понятных шаблонов. Суть которого заключается в создании\получении единственного экземпляра класса.
Где это может быть полезно? Очевидно, единственный экземпляр класса БД, кеширование, доступ к какому либо API (к примеру AdWords) и т.д.
Но пойдем немножко дальше и совместим "Одиночку" с шаблоном Factory (этакий гибрид). В классическом понимании, Factory, при каждом вызове создает новый экземпляр класса, но надо ли оно нам?
Необходимо отметить, что применени паттерна не означает невозможность создание нового экземпляра класса.
PHP:
# Как этим пользоваться, в приведенном примере обратите внимание на ID экземпляров класса dechex(crc32(spl_object_hash($this)))
class MySqlDb extends \Patterns\ISingleton
{
public function __construct($dbHost,$dbUser,$dbPass) { echo '<pre>'.__METHOD__.' #'.dechex(crc32(spl_object_hash($this)))." $dbHost,$dbUser,$dbPass ".PHP_EOL.'</pre>';}
public function Connect($DSN) {}
public function Query($Sql) { echo '<pre>'.__METHOD__.' #'.dechex(crc32(spl_object_hash($this))).PHP_EOL.'</pre>';}
public function Close() {}
}
/**
* @var MySqlDb
*/
$Dbi = MySqlDb::Instance('localhost','user','test');
# OUTPUT: MySqlDb::__construct #f4f605e1 localhost,user,test
$Dbi->Query("SELECT ....");
# OUTPUT: MySqlDb::Query #f4f605e1
$c = new MySqlDb;
# OUTPUT: MySqlDb::__construct #d46479aa ,,
MySqlDb::Instance()->Query("UPDATE ...");
# OUTPUT: MySqlDb::Query #f4f605e1
$c->Query("DELETE ...");
# OUTPUT: MySqlDb::Query #d46479aa
\Patterns\ISingleton::Factory('MySqlDb')->Close();
# OUTPUT: MySqlDb::Close #f4f605e1
class Sphinx
{
public function __construct($dbHost,$dbUser,$dbPass) { echo '<pre>'.__METHOD__.' #'.dechex(crc32(spl_object_hash($this)))." $dbHost,$dbUser,$dbPass ".PHP_EOL.'</pre>';}
public function Connect($DSN) {echo '<pre>'.__METHOD__.' #'.dechex(crc32(spl_object_hash($this))).PHP_EOL.'</pre>';}
}
# Обратите внимание, что класс Sphinx не наследует шаблон Singleton, но при этом через Factory, мы всегда будем получать единственный экземпляр класса
\Patterns\ISingleton::Factory('Sphinx','aaa','bbb','ccc');
# OUTPUT: Sphinx::__construct #85315e7b
\Patterns\ISingleton::Factory('Sphinx')->Connect();
# OUTPUT: Sphinx::Connect #85315e7b
PHP:
namespace Patterns;
function Exception($Class,$Method,$Message,$Code=0) { throw new \Exception("$Class::$Method ".$Message,$Code);}
abstract class ISingleton {
static private $_Objects;
static public function Instance() {
# эта функция появилась с пхп 5.3, и основная ее полезняшка, применимая к Singleton, в том, что она возвращает имя класса вызвавшего статический метод
$Class = get_called_class();
# использование Reflection оправдано в том случае если необходимо при создании нового экземпляра класса передать в конструктор параметры
!isset(self::$_Objects[$Class]) && ($reflect = new \ReflectionClass($Class)) && (self::$_Objects[$Class] = $reflect->newInstanceArgs(func_get_args()));
return self::$_Objects[$Class];
}
static public function Factory($Class) {
# пробуем найти класс, и вызвать все autoload - ры, возможно впринципе и самому делать include-ы классов, но оно надо?
!class_exists($Class, true) && \Patterns\Exception(__CLASS__, __METHOD__, 'Class not found');
$args = array_slice(func_get_args(), 1);
!isset(self::$_Objects[$Class]) && ($reflect = new \ReflectionClass($Class)) && (self::$_Objects[$Class] = $reflect->newInstanceArgs($args));
return self::$_Objects[$Class];
}
public function __clone() { trigger_error(__CLASS__.' can not be cloned.', E_USER_ERROR); }
}
PS: Decorator, Adpater .... coming soon