Реализация Singleton в PHP5

Ilya Bous

Новичок
Реализация Singleton в PHP5

Однако приватный конструктор имеется. Следующий код работает без проблем.

PHP:
<?
class Singleton
{
	static $instance=null;

	private function __construct()
	{
		echo "shalala in constructor<br>";
	}

	public static function instance()
	{
		if (Singleton::$instance == null)
		{
			Singleton::$instance = new Singleton;
		}

		echo "shalala in instance()<br>";

		return Singleton::$instance;
	}
	
}

$a = Singleton::instance();
$b = Singleton::instance();
?>
 

Ilya Bous

Новичок
А вопроса собственно нет. Это пост в догонку прошедшей конференции.
 

tony2001

TeaM PHPClub
Ilya Bous
20 минут назад на обеде я то же самое сказал Антохе =)
однако, есть.
однако, непонятно почему кому-то их не хватало, если они есть.
 

Domovoj

Guest
Меня интересует каким образом можно реализовать наследника от Singleton класса? Это вообще воможно?

К сожалению, следующий пример не работает:

PHP:
class AbstractApplication {
    private static $instance = null;
    private function __construct() {
        ....
    }
    public static function getInstance() {
        if (self::$instance == null) {
            $className = __CLASS__;
            self::$instance = new $className();
        }
        return self::$instance;
    }
}

class Application extends AbstractApplication {
}

$application = Application::getInstance();
В $application будет объект класса AbstractApplication, т.к. __CLASS__ возвращает имя того класса, в методе которого она используется.

Есть у кого какие идеи?
 

Domovoj

Guest
Originally posted by Profic
интересно, а конструкция вида
new self() работает %)
У меня были такие идеи. :)
Но это создаёт (пытается) объект класса self...

Я вроде бы даже так пробовал:
= new self::();
:)

Наверно, всё-таки придётся переопределять метод getInstance()...


Кстати, заметил инетересную особенность: self:: тоже генерирует вызов метода(или переменной) того объекта, где объявлено (как и __CLASS__). В итоге в наследниках будет метод предка вызываться, даже если он переопределён. Что самое интересное, если в методе есть два self:: и первый заменить на getClass(), то второй также начинает работать правильно!

Мистика! :)

-~{}~ 29.11.04 16:54:

Облазил кучу забугорных форумов и, кажется, нашёл:

PHP:
class SomeClass {
        
        static protected $instance = false;
        
        protected function __construct() {
                ....
        }

        public function getInstance() { 
                if(!self::$instance) { 
                        self::$instance = new self; 
                } 
                return self::$instance; 
        }
}
Вечером сегодня попробую в деле эту конструкцию.

-~{}~ 29.11.04 16:56:

Ошибка:

должно быть конечно:
PHP:
static public function getInstance()  {
 

Domovoj

Guest
Originally posted by Domovoj
У меня были такие идеи. :)
Но это создаёт (пытается) объект класса self...

Я вроде бы даже так пробовал:
= new self::();
:)

Наверно, всё-таки придётся переопределять метод getInstance()...


Кстати, заметил инетересную особенность: self:: тоже генерирует вызов метода(или переменной) того объекта, где объявлено (как и __CLASS__). В итоге в наследниках будет метод предка вызываться, даже если он переопределён. Что самое интересное, если в методе есть два self:: и первый заменить на getClass(), то второй также начинает работать правильно!

Мистика! :)

-~{}~ 29.11.04 16:54:

Облазил кучу забугорных форумов и, кажется, нашёл:

PHP:
class SomeClass {
        
        static protected $instance = false;
        
        protected function __construct() {
                ....
        }

        public function getInstance() { 
                if(!self::$instance) { 
                        self::$instance = new self; 
                } 
                return self::$instance; 
        }
}
Вечером сегодня попробую в деле эту конструкцию.

-~{}~ 29.11.04 16:56:

Ошибка:

должно быть конечно:
PHP:
static public function getInstance()  {
Нет. Не работает.
Если сделать:
PHP:
class A extends SomeClass {
}

$a = A::getInstance();

echo(get_class($a));
то будет выведено "SomeClass", а не "A".

Кто-нибудь знает как это лечится?
 

Profic

just Profic (PHP5 BetaTeam)
раздели реализацию
singleton отдельно
нормальные класы отдельно
и просто явно передавай в нужный синглтон нужное имя класса
 

Domovoj

Guest
Originally posted by Profic
раздели реализацию
singleton отдельно
нормальные класы отдельно
и просто явно передавай в нужный синглтон нужное имя класса
Да собственно говоря так и есть.
Я просто хотел узнать если вообще возможность наследовать Singleton классы без переписывания метода getInstance().
Похоже, что нет...

Пример:
Есть некий AbstractApplication где содержится основная логика работы с web-приложением + абстрактная функция для чего-либо.

При написании конкретного приложения AbstractApplication расширяется до MyApplication с переопределением этой функции.

Так вот, в момент наследования хотелось бы отвлечьтся от конкретики реализации AbstractApplication (что это singleton) и просто переопределить изменяемые методы, не трогая getInstance().

Насколько я понимаю, такой возможности нет, а ключевое слово self является "статическим" и указывает на тот класс, в методе которого он используется (т.е. при наследовании оно всё равно указывает на класс-предок).
 

vitus

мимо проходил
:) синглетон, он на то и синглетон :)
его наследовать безмазы, иначе он сразу перестанет быть синглетоном, если ты создашь новый инстанс его наследника, то создашь и его новый инстанс, вот такая белиберда.

а вообще есть определённое сомнение в его необходимости в однотредовом приложении.
----added----
и потом клонировать объект, вродебы как, никто не зарещает ...
 

Profic

just Profic (PHP5 BetaTeam)
PHP:
class {
    ...
    private function __clone () {}
    ...
}
и никакого клона %)
 
Сверху