PHP5 클래스를 사용하여 어떻게 싱글 톤 클래스를 만들 수 있습니까?
답변
/**
* Singleton class
*
*/
final class UserFactory
{
/**
* Call this method to get singleton
*
* @return UserFactory
*/
public static function Instance()
{
static $inst = null;
if ($inst === null) {
$inst = new UserFactory();
}
return $inst;
}
/**
* Private ctor so nobody else can instantiate it
*
*/
private function __construct()
{
}
}
쓰다:
$fact = UserFactory::Instance();
$fact2 = UserFactory::Instance();
$fact == $fact2;
그러나:
$fact = new UserFactory()
오류가 발생합니다.
정적 변수 범위 및 설정 작동 이유를 이해하려면 http://php.net/manual/en/language.variables.scope.php#language.variables.scope.static 을 참조 하십시오static $inst = null;
.
답변
PHP 5.3에서는 늦은 정적 바인딩을 통해 상속 가능한 Singleton 클래스를 만들 수 있습니다.
class Singleton
{
protected static $instance = null;
protected function __construct()
{
//Thou shalt not construct that which is unconstructable!
}
protected function __clone()
{
//Me not like clones! Me smash clones!
}
public static function getInstance()
{
if (!isset(static::$instance)) {
static::$instance = new static;
}
return static::$instance;
}
}
이것은 PHP 5.3 이전에 싱글 톤을 확장 한 클래스가 자신의 부모 클래스의 인스턴스를 생성하는 것이 아니라는 문제를 해결합니다.
이제 할 수있는 일 :
class Foobar extends Singleton {};
$foo = Foobar::getInstance();
그리고 $ foo는 Singleton 인스턴스 대신 Foobar 인스턴스가됩니다.
답변
불행히도 여러 개의 서브 클래스가있는 경우 Inwdr의 답변 이 중단됩니다.
올바른 상속 가능한 Singleton 기본 클래스는 다음과 같습니다.
class Singleton
{
private static $instances = array();
protected function __construct() {}
protected function __clone() {}
public function __wakeup()
{
throw new Exception("Cannot unserialize singleton");
}
public static function getInstance()
{
$cls = get_called_class(); // late-static-bound class name
if (!isset(self::$instances[$cls])) {
self::$instances[$cls] = new static;
}
return self::$instances[$cls];
}
}
테스트 코드 :
class Foo extends Singleton {}
class Bar extends Singleton {}
echo get_class(Foo::getInstance()) . "\n";
echo get_class(Bar::getInstance()) . "\n";
답변
싱글 톤 패턴을 만드는 실제적이고 현대적인 방법은 다음과 같습니다.
<?php
/**
* Singleton Pattern.
*
* Modern implementation.
*/
class Singleton
{
/**
* Call this method to get singleton
*/
public static function instance()
{
static $instance = false;
if( $instance === false )
{
// Late static binding (PHP 5.3+)
$instance = new static();
}
return $instance;
}
/**
* Make constructor private, so nobody can call "new Class".
*/
private function __construct() {}
/**
* Make clone magic method private, so nobody can clone instance.
*/
private function __clone() {}
/**
* Make sleep magic method private, so nobody can serialize instance.
*/
private function __sleep() {}
/**
* Make wakeup magic method private, so nobody can unserialize instance.
*/
private function __wakeup() {}
}
그래서 지금처럼 사용할 수 있습니다.
<?php
/**
* Database.
*
* Inherited from Singleton, so it's now got singleton behavior.
*/
class Database extends Singleton {
protected $label;
/**
* Example of that singleton is working correctly.
*/
public function setLabel($label)
{
$this->label = $label;
}
public function getLabel()
{
return $this->label;
}
}
// create first instance
$database = Database::instance();
$database->setLabel('Abraham');
echo $database->getLabel() . PHP_EOL;
// now try to create other instance as well
$other_db = Database::instance();
echo $other_db->getLabel() . PHP_EOL; // Abraham
$other_db->setLabel('Priler');
echo $database->getLabel() . PHP_EOL; // Priler
echo $other_db->getLabel() . PHP_EOL; // Priler
보시다시피이 실현은 훨씬 유연합니다.
답변
인스턴스 복제를 허용하지 않으려면 전용 __clone () 메서드를 추가해야합니다.
private function __clone() {}
이 방법을 포함하지 않으면 다음이 가능해집니다.
$inst1=UserFactory::Instance(); // to stick with the example provided above
$inst2=clone $inst1;
이제 $inst1
! == $inst2
-더 이상 같은 인스턴스가 아닙니다.
답변
<?php
/**
* Singleton patter in php
**/
trait SingletonTrait {
protected static $inst = null;
/**
* call this method to get instance
**/
public static function getInstance(){
if (static::$inst === null){
static::$inst = new static();
}
return static::$inst;
}
/**
* protected to prevent clonning
**/
protected function __clone(){
}
/**
* protected so no one else can instance it
**/
protected function __construct(){
}
}
쓰다:
/**
* example of class definitions using SingletonTrait
*/
class DBFactory {
/**
* we are adding the trait here
**/
use SingletonTrait;
/**
* This class will have a single db connection as an example
**/
protected $db;
/**
* as an example we will create a PDO connection
**/
protected function __construct(){
$this->db =
new PDO('mysql:dbname=foodb;port=3305;host=127.0.0.1','foouser','foopass');
}
}
class DBFactoryChild extends DBFactory {
/**
* we repeating the inst so that it will differentiate it
* from UserFactory singleton
**/
protected static $inst = null;
}
/**
* example of instanciating the classes
*/
$uf0 = DBFactoryChild::getInstance();
var_dump($uf0);
$uf1 = DBFactory::getInstance();
var_dump($uf1);
echo $uf0 === $uf1;
respose :
object(DBFactoryChild)#1 (0) {
}
object(DBFactory)#2 (0) {
}
PHP 5.4를 사용하는 경우 : 옵션의 특성 을 나타내므로 Singleton 패턴 을 얻기 위해 상속 계층 구조를 낭비하지 않아도됩니다.
사용 여부도 통지 있다는 특성을 또는 싱글 확장 클래스를 하나 개의 느슨한 끝은 다음 코드 행을 추가 해달라고하면 자식 클래스의 싱글 톤을 만드는 것이 었습니다 :
protected static $inst = null;
어린이 수업에서
예기치 않은 결과는 다음과 같습니다.
object(DBFactoryChild)#1 (0) {
}
object(DBFactoryChild)#1 (0) {
}
답변
protected static $_instance;
public static function getInstance()
{
if(is_null(self::$_instance))
{
self::$_instance = new self();
}
return self::$_instance;
}
이 코드는 클래스 이름을 신경 쓰지 않고 모든 클래스에 적용될 수 있습니다.
