Шаблоны проектирования

Шаблоны - это способ описания оптимальных методов и хороших дизайнов проектирования. Они предоставляют универсальные пути решения общих проблем программирования.

Фабрика (Factory)

Шаблон Фабрика позволяет создавать объекты во время работы программы. Этот шаблон называется Фабрикой потому, что он отвечает за производство объекта. Параметризированная фабрика принимает в качестве аргумента имя класса, объект которого создается.

Пример #1 Параметризированный фабричный метод

<?php
class Example
{
    
// Параметризированный фабричный метод
    
public static function factory($type)
    {
        if (include_once 
'Drivers/' $type '.php') {
            
$classname 'Driver_' $type;
            return new 
$classname;
        } else {
            throw new 
Exception('Драйвер не найден');
        }
    }
}
?>

Определение этого метода в классе позволяет драйверам быть загруженными "на лету". В случае, если класс Example был бы классом абстрактного доступа к базе данных, то загрузка драйвера MySQL и SQLite может быть выполнена следующим образом:

<?php
// Загрузка драйвера MySQL
$mysql Example::factory('MySQL');

// Загрузка драйвера SQLite
$sqlite Example::factory('SQLite');
?>

Синглтон (Singleton)

Шаблон проектирования Синглтон применяется в тех ситуациях, когда нужно получить единственный экземпляр класса. Синглтон является одним из четырех("Gang of Four") основных создающих шаблонов.

Синглтон обычно применяется в классах для баз данных, логирования, контроллеров(Front Controller) и объектах, определяющих запросы и ответы(Request и Response).

Пример #2 Пример Синглтона

<?php
class Example
{
    private static 
$instance;
    private 
$count 0;

    private function 
__construct()
    {
    }

    public static function 
singleton()
    {
        if (!isset(
self::$instance)) {
            echo 
'Создание нового экземпляра.';
            
$className __CLASS__;
            
self::$instance = new $className;
        }
        return 
self::$instance;
    }

    public function 
increment()
    {
        return 
$this->count++;
    }

    public function 
__clone()
    {
        
trigger_error('Клонирование запрещено.'E_USER_ERROR);
    }

    public function 
__wakeup()
    {
        
trigger_error('Десериализация запрещена.'E_USER_ERROR);
}

?>

Пример ниже иллюстрирует использование Синглтона

<?php
$singleton 
Example::singleton(); // выведет "Создание нового экземпляра."
echo $singleton->increment(); // 0
echo $singleton->increment(); // 1

$singleton Example::singleton(); // вернет тот же самый экземпляр
echo $singleton->increment(); // 2
echo $singleton->increment(); // 3

// все строки ниже вызывают неисправимую ошибку
$singleton2 = new Example;
$singleton3 = clone $singleton;
$singleton4 unserialize(serialize($singleton));
?>
Внимание

Паттерн Синглтон является одним из наиболее противоречивых паттернов. Критики утверждают, что Синглтоны вводят глобальные состояния при их применении и тесно связывают Синглтон и использующие его классы. Это приводит к скрытой зависимости и неожиданным побочным эффектам, что в свою очередь приводит к коду, который сложнее тестировать и поддерживать.

Критики также утверждаю, что не имеет смысла использовать Синглтон в архитектурах "ничего общего" (Shared Nothing Architecture), таких как PHP, где объекты являются уникальными в пределах запроса и никак иначе. Проще и аккуратнее создавать структуры взаимосвязанных объектов с помощью шаблонов Строителей(Builders) и Фабрики(Factory) за один раз в начале запроса.

Синглтоны также нарушают некоторые из "Жестких" принципов ООП проектирования и Закон Деметры. Синглтоны нельзя сериализовывать. Они не могут быть подклассами (до PHP 5.3) и не будут собираться сборщиком мусора из-за того, что экземпляр хранится в статическом атрибуте Синглтона.

Коментарии

I struggled a few hours on writing a simple Generic factory method for dynamic object factoring. I initially went for call_user_func_array() to create the object but that obviously didn't work. An anonymous function was what I needed. Here's the result (PHP5):

<?php
/**
 *    Name:    Factory
 *    Author:    Ezku
 *    Contact:    dmnEe0 at gmail dot com
 */
class Factory
{
   
/**
     * Generic factory method
     * @param string    Path to class definition
     * @param string    Basic class name
     * @param string    Derived class name
     * @param array    Class constructor arguments, optional
     */
   
public static function Generic($filename$base$derived$args = array())
    {
       
/**
         * Check that the file exists
         */
       
if(file_exists($filename))
        {
            include_once 
$filename;
           
/**
             * Check that the file contained the appropriate class definition
             */
           
if(class_exists($derived))
            {
               
/**
                 * Create argument list for constructor
                 */
               
$arglist = array();
                for(
$i 0$n count($args); $i $n$i++)
                   
$arglist[] = '$args['.$i.']';
               
$arglist implode(',',$arglist);
               
               
/**
                 * Create new instance via an anonymous function
                 */
               
$new_class create_function('$name, $args''return new $name('.$arglist.');');
                return 
$new_class($derived$args);
            }
            else
                throw new 
Exception("Definition file ($filename) did not contain definition for the $base class <code>$derived</code>");
        }
        else
            throw new 
Exception("Definition file ($filename) for the $base class <code>$derived</code> was not found");
    }
}

/**
 * Useless usage example:
 */
function createCat($name$scary_eyes FALSE$whiskers TRUE)
{
   
$path PATH_ANIMALS.'/'.$name.'.php';
   
$base 'Cat';
   
$derived $name.$base;
   
$args = array($scary_eyes$whiskers);
    return 
Factory::Generic($path$base$derived$args);
}

// Create a MeowCat with scary eyes and whiskers
$cat createCat('Meow'TRUE);
// Do whatever
?>
2005-05-14 17:13:26
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
After programming a number of real world applications with PHP, I found that this version of the singleton doesn't really resemble other singleton patterns, but is the only one I've ended up using and it works great.

<?php

class User {
   
/* .. your code, nothing specific matters in the class .. */
}

function 
user(){
    static 
$user;
    if(!isset(
$user))
       
$user = new User();
    return 
$user;
}

//creates the user object then calls a method on it
user()->doSomething();

//calls a method on the same object
user()->doSomethingElse();

?>

Note that it is *possible* to create multiple instances of User, but in your API docs, or when you tell people how to use the class just say you are supposed to refer to it only via the user() function, and then there should be no reason to enforce it in your code any other way.

Also note that this syntax is only possible in PHP 5 because of the object / function dereferencing feature.  user()->someMethod(); will throw a fatal error in 4.x
2005-05-23 16:02:13
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Автор:
Here's an effective strategy for creating singletons.

1.) define an __autoload() function

2.) Define all properties of a class to be static

3.) Make the constructor private.

Now, anywhere in your code, you can simply do as follows:

Class::Function();

The __autoload() function will take care of loading the class.

It's even better when you use the auto_prepend directive to define __autoload(). Now you can create a php script which looks like this:

<?php
TemplateSystem
::Start();
echo 
'This is just a test!';
TemplateSystem::Stop();
?>

Now you've effectively got a 2-line solution to all templating issues, the templates will be available to every script, and the only additional overhead that you'll have for scripts that don't use the templating system is a 3-line autoload function!

Obviously, there's still a problem with __autoload() if you are attempting to write a templating system that has to work with someone else's software that also defines __autoload(). The best advice I can give here is to remove one of the __autoload()'s and modify the other to work with both.
2005-07-03 02:28:08
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Please use design patterns as they were intended:

Design patterns are designs that are known to solve common problems, such as having only 1 instance of a class. Design patterns are are not code libraries.
Most design patterns, if not all, have alternate implementations but common to them all is that the recommended implementation solves the problem.

Singleton should not be made as a class and then extended. Nor shuld __autoload be used.
Autoloading is very PHP-specific (and there might be nothing wrong with that, but design patterns are general patterns that are abstracted from the implementing language).
Making a class that you extend is very ugly. What if you have to extend that class too? You will have to make a dummy that extends your singleton class, just so you can extend the class you want. This is a very "ugly" solution that completely overrules the idea of well known design patters: A thought-though idea that works the way intended.

The manual shows a PHP implementation of the standard Singleton-pattern without "nifty" modifications.

To finish off this lesson on design patterns, I would like to ackknowledge that there is nothing wrong in tweaking patterns to suit your needs.
But remember: "If it isn't broken - don't fix it".
2005-07-07 12:46:15
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Hi ,

Singleton Patterns are excellent ,
I have created a singleton pattern that enables any class to be loaded from the one modular singleton library.

<?php

   
class singleton
   
{
        private static 
$o_instance NULL ;

        public static function 
call_singleton $s_class )
        {
            if ( 
class_exists $s_class ) )
            {
                if ( 
self :: $o_instance === NULL )
                {
                   
self :: $o_instance = new $s_class ;
                }
            }           
            return 
self :: $o_instance ;
        }
    }

?>
2005-07-08 02:57:35
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
If you need singleton of any class and don't want write singleton wrapper for each this class, try this:

<?php
class UniverzalSingleton {

    const 
EXCEPTION_NO_CLASS 1;

    protected static 
$_instances = array();

    public static function 
getInstance($class) {
        if (!isset(
self::$_instances[$class])) {
            if (!
class_exists($class))
                throw (new 
Exception(__CLASS__ ': Requsted class is not exist.'self::EXCEPTION_NO_CLASS));
           
self::$_instances[$class] = new $class();
        } 
// if
       
return self::$_instances[$class];
    } 
// getInstance

// class UniverzalSingleton
?>
2005-07-17 04:12:44
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Short version of Singleton:
<?php
public function __clone()
    {
       
trigger_error('Clone is not allowed.'E_USER_ERROR);
    }
?>
   
is : 
<?php private function __clone() {} ?>
2005-10-05 12:25:15
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Regarding the singleton pattern, you have to create the function for every singleton class you want to have, because settting a variable static will set the variable on all instances of the class, and second of all, by extending a singleton class, you are breaking rule No #1 of the singleton pattern. an instance of a given type may only excist ONCE, by extending the singleton class you have multiple instances of the singleton class, and by is sharing the static $instance variable.

on thing could be done though, to make sure a programmer does not make any mistakes when creating singleton classes, an interface could be made, to make sure the singleton class is correctly defined.

it could look something like this:

<?php
interface singleton {
    public static function 
getInstance();
}
?>

however, this interface does NOT force the programmer to make the constructor private, and don't even bother to try, it would just result in a error.

sorry to say it guys, there are no easy way around this one. not even a factory class can do the job for you since, the constructor must be private, to ensure that only one instance excists.
2005-10-11 10:47:32
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
The principle of the Singleton pattern can easily be expanded to form [what I have dubbed as] the 'Unique' pattern - where a particular class may have several instances, each with a 'Unique ID'.  This can be useful when a single instance is required for each database record.

<?php

 
// Each instance of 'Customer' represents one customer!
 
class Customer {

     
// Access a unique instance of class for a customer record
     
public function Unique($CustomerID) {
       static 
$instances = array();

       
// a unique instance for each CustomerID
       
if(!isset($instances[$CustomerID]))
         
$instances[$CustomerID] = new Customer($CustomerID);

       return 
$instances[$CustomerID];
     }

     private 
$CustomerID;

     private function 
__construct($CustomerID) {
       
$this->CustomerID $CustomerID;
     }
  }

 
// get instance of class for customer #1
 
$C1 Customer::Unique(1);

 
// get instance of class for customer #2
 
$C2 Customer::Unique(2);

?>
2005-11-27 07:46:56
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Singleton is a very useful pattern if you need multiple instances of different classes to use only one unique instance of common class. It's not just about having static methods.

e.g. Your database connection class probably should be a singleton, in order to spare all redundant connect calls, etc...
2006-01-29 22:39:19
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
I don't agree to take a class with only static members and static methods as a 'singleton'. According to GoF's book, the singleton pattern means a class that only have one instance. A class containing only static members and functions still can be instantiated and extended, it have multiple instances. Consider the code below:
<?php

class StaticTest
{
    private static 
$_test "aaa";
   
    public static function 
test()
    {
        echo 
self::$_test;
    }
}

$obj = new StaticTest();

?>
The code will not report errors(although it's useless). So there can be many instances of the class.

It's reasonable that there is a class that create and store a unique instance of another class. Such as:
<?php

class A
{
    private 
$_id 0;
    public function 
getId()
    {
        return 
$this->_id;
    }
}

class 
B
{
    private static 
$_instance;

    public static function 
singleton() 
    {
        if (!isset(
self::$_instance)) {
           
self::$instance = new A();
        }
        return 
self::$instance;
    }
}

?>
Here class B act as a guard to class A. But as same as the first section, it's useless too! Unless you can make sure that the users of your class will never find the class A, you shouldn't make the class you wanna to be unique can be instantiated many times.

So the best way to create a unique instance of a class is that the class save the unique instance itself. It is the core meaning of singleton pattern. Any information that mentioned here can be found in the book of GoF. I think it's worth reading the book.

BTW: It's allowed that there are a few of subclasses of a singleton class.
2006-04-29 06:15:20
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
It's often forgotten, but a singleton class MUST be final. So it's useless to have a base class that implements the pattern and to inherit of it. That's why it's called a pattern and not a class library.

Here a little example that will show why.

<?php
class {
// singleton pattern with getInstance static method
private $var// A ressource variable
function __construct() {
   
$this->var "get a ressource that could only  be taken one time by process";
}
}

class 
extends {
// singleton pattern
function __construct() {
   
parent::__construct();
}
}

$anA :: getInstance();
$aB :: getInstance(); // try to get a second ressource, :(

?>

When developping class A, you may have think to be the only one with a $var ressource, but it's completly wrong. As $aB is an A (Think that there is two A instanciate and one with more than just A), $anA and $aB will have a different ressource variable and thus two different database connection for eg.

You'd never know how will be used your code, so you need to make it strong. This is the way of poo thinking.
2006-06-02 16:27:00
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Автор:
An easy way to have your singleton persistent between page loads:

<?php
/**
 *    Returns an instance of the singleton class.
 *    @return    object        The singleton instance
 */
public static function _instance() 
{
   
// Start a session if not already started
   
Session::start();
   
    if ( 
false == isset( $_SESSIONself::$_singleton_class ] ) )
    {
       
$class self::$_singleton_class;
       
$_SESSIONself::$_singleton_class ] = new $class;
    }
   
    return 
$_SESSIONself::$_singleton_class ];       
}

/**
 *    Destroy the singleton object. Deleting the session variable in the
 *    destructor does not make sense since the destructor is called every
 *    time the script ends.
 */
public static function _destroy() 
{
   
$_SESSIONself::$_singleton_class ] = null;
}

/**
 *    Initialize the singleton object. Use instead of constructor. 
 */
public function _initialize$name 
{
   
// Something...
}

/**
 *    Prevent cloning of singleton.
 */
private function __clone() 
{
   
trigger_error"Cloning a singleton object is not allowed."E_USER_ERROR );
}

private static 
$_singleton_class __CLASS__;
?>
2006-08-11 15:19:48
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
It's sometimes useful to let one sigleton class extend another. You can achieve this by only using static attributes:

<?php
 
class {
    private static 
$value 0;
    private static 
$instance null;
   
    private function 
__construct() {
     
$this->set(time());
    }
   
    public static function 
getInstance() {
      if (
is_null((self::$instance))) {
       
$class_name __CLASS__;
       
self::$instance = new $class_name;
      } 
     
      return 
self::$instance;
    }
   
    private function 
set($i) {
     
self::$value $i;
     
$this->out();
    }
   
    public function 
out() {
      echo 
self::$value;
    }
  }

  class 
extends {
    public static 
$instance null;
   
    public static function 
getInstance() {
     
parent::getInstance();
      if (
is_null(self::$instance)) {
       
$class __CLASS__;
       
self::$instance = new $class;
      }
      return 
self::$instance;
    }
  }

 
$b B::getInstance();
 
$b->out();
?>

This will output the current time twice. If $value isn't static, the call to $b->out() will output 0. Maybe it can save someone some time...
2006-09-29 20:38:08
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
A pure extendable(multiple sublevels) Singleton class in PHP seems impossible at the moment because of the way PHP handles static inheritance, but my class is close to what i want. 

Very simple usage:

<?php
class Test extends Singleton {

    public static function 
getInstance(){
        return 
Singleton::getSingleton(get_class());
    }

}
?>

Singleton class implementation:

<?php
class Singleton {

   
/***********************
     * HOW TO USE
     * 
     * Inherit(extend) from Singleton and add getter:
     * 
     *  //public getter for singleton instance
     *     public static function getInstance(){
     *        return Singleton::getSingleton(get_class());
     *    }
     * 
     */
   
   
private static $instanceMap = array();

   
//protected getter for singleton instances
   
protected static function getSingleton($className){
        if(!isset(
self::$instanceMap[$className])){
           
           
$object = new $className;
           
//Make sure this object inherit from Singleton
           
if($object instanceof Singleton){   
               
self::$instanceMap[$className] = $object;
            }
            else{
                throw 
SingletonException("Class '$className' do not inherit from Singleton!");
            }
        }
       
        return 
self::$instanceMap[$className];
    }   
   
   
//protected constructor to prevent outside instantiation
   
protected function __construct(){
    }
   
   
//denie cloning of singleton objects
   
public final function __clone(){
       
trigger_error('It is impossible to clone singleton'E_USER_ERROR);
    }   
}
?>

Just a simple test case:

<?php
class extends Singleton {
   
    protected 
$rndId;
   
    protected function 
__construct(){
       
$this->rndId rand();
    }   
   
    public function 
whatAmI(){
        echo 
'I am a A('.$this->rndId.')<br />';
    }

    public static function 
getInstance(){
        return 
Singleton::getSingleton(get_class());
    }

}

class 
extends {

    public function 
whatAmI(){
        echo 
'I am a B('.$this->rndId.')<br />';
    }
   
    public static function 
getInstance(){
        return 
Singleton::getSingleton(get_class());
    }

}

$a A::getInstance();
$b B::getInstance();

$a->whatAmI();// should echo 'I am a A(some number)
$b->whatAmI();// should echo 'I am a B(some number)

$a A::getInstance();
$b B::getInstance();

$a->whatAmI();// should echo 'I am a A(same number as above)
$b->whatAmI();// should echo 'I am a B(same number as above)

$a = new A();// this should fail
$b = new B();// this should fail

?>

I hope this helps.
-Eyvind-
2006-12-06 11:48:47
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Автор:
Here's a way to make singleton classes with no extra code other than "extends Singleton" - if you use __AutoLoad() and keep each class in a separate file that is...

<?php

abstract class Singleton {
 
 
// Cannot be instantiated by any other class
 
protected function __Construct() { }
 
 
// Cannot be cloned ever
 
private function __Clone() { }
 
 
// Create/fetch an instance of the class
 
static public function getInstance($ClassName null) {
   
    static 
$Instance;
   
    if (
$Instance) {
      return 
$Instance;
    } elseif (
$ClassName) {
     
$Instance = new $ClassName;
      return 
$Instance;
    } else {
      return 
null// or throw exception if you want...
   
}
   
  }
 
}

function 
__AutoLoad($ClassName) {
  include 
"$ClassName.php";
  if (
is_subclass_of($ClassName'Singleton')) {
    eval(
$ClassName.'::getInstance($ClassName);');
  }
}

// ClassName.php
class ClassName extends Singleton {
 
// ... Code ...
}

// To use
$a ClassName::getInstance();
$a->MyFunc();

?>

Of course you could do this differently - the point is that you can use __AutoLoad() to tell the single what class it is, unlike some other ways where this is done manually every time you define a singleton class.
2007-03-25 05:12:39
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
This's a example of Composite Pattern:

<?php
abstract class Graphic{
    abstract public function 
draw();
}

class 
Triangle extends Graphic{
    private 
$name '';

    public function 
__construct($name 'unknown'){
       
$this->name $name;
    }

    public function 
draw(){
        echo 
'-I\'m a triangle '.$this->name.'.<br>';
    }
}

class 
Container extends Graphic{
    private 
$name '';
    private 
$container = array();

    public function 
__construct($name 'unknown'){
       
$this->name $name;
    }

    public function 
draw(){
        echo 
'I\'m a container '.$this->name.'.<br>';
        foreach(
$this->container as $graphic)
           
$graphic->draw();
    }

    public function 
add(Graphic $graphic){
       
$this->container[] = $graphic;
    }

    public function 
del(Graphic $graphic){
        unset(
$this->container[$graphic]);
    }
}

$tri1 = new Triangle('1');
$tri2 = new Triangle('2');
$tri3 = new Triangle('3');

$container1 = new Container('1');
$container2 = new Container('2');
$container3 = new Container('3');

$container1->add($tri1);
$container1->add($tri2);
$container2->add($tri3);

$container3->add($container1);
$container3->add($container2);

$container3->draw();
?>

The above example will output:

I'm a container 3.
I'm a container 1.
-I'm a triangle 1.
-I'm a triangle 2.
I'm a container 2.
-I'm a triangle 3.

Dario Ocles.
2007-06-18 18:09:24
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Simplest PHP5 singleton implementation ever:

<?php
class Some_Class
{
    static private 
$_i;
    private function 
__construct()
    {
    }
    static public function 
singleton() {
        return isset(
self::$_i) ? self::$_i self::$_i = new self();
    }
}
?>
2008-01-09 15:01:00
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Автор:
This allows for singleton functionality via class extension, and does not use any shady functions like eval.

<?php
interface ISingleton {
    public static function 
GetInstance();
}

class 
Singleton implements ISingleton {
    public static function 
GetInstance($class='Singleton') {
        static 
$instances = array();
       
        if (!
is_string($class)) {
            return 
null;
        }
       
        if (
$instances[$class] === null) {
           
$instances[$class] = new $class;
        }
       
        return 
$instances[$class];
    }
}

class 
Mars extends Singleton implements ISingleton {
    public static function 
GetInstance() {
        return 
Singleton::GetInstance(get_class());
    }
}

class 
Neptune extends Singleton implements ISingleton {
    public static function 
GetInstance() {
        return 
Singleton::GetInstance(get_class());
    }
}

$x Mars::GetInstance();
echo 
'<pre>'.print_r($x,true).'</pre>';

$x Neptune::GetInstance();
echo 
'<pre>'.print_r($x,true).'</pre>';
?>
2008-02-21 10:16:07
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
If you want a singleton and you don't mind on throwing a stop error/exception when a 2nd instace is created instead of returning the already created object, then this code works with subclassing and without getInstace alike functions (just with __construct)

<?php

class SINGLETON
{
   
// the array for checking the created instances
   
protected static $singletons = array ();

   
// make it final so extended classes cannot override it
   
final public function __construct ()
    {
       
$classname get_class $this );

        if ( ! isset ( 
self::$singletons[$classname] ) )
           
// instead of $this it could be any value since we are checking for isset, but a reference to the object may be useful in a possible improvement, somewhat
           
self::$singletons[$classname] = $this;
        else
           
// your favorite stop error here
           
trow new Exception ();
    }

   
// final as well, no overriding, plus protected so it cannot be called
   
final protected function __clone () {}
}

class 
extends SINGLETON
{
   
//...
}

class 
extends X
{
   
//...
}

$x = new ();
$y = new ();

$a = new (); // execution stops, as an instance of X is created already

$b = new (); // execution stops, as an instance of Y is created already, it DOES NOT give problems with X, despite extending X

?>

so, if it is ok to stops the execution, this method is way simpler

it must stops the execution because no matter what, __construct will return a reference to the new object, always, so if the script goes on further you will have effectively 2 instances (as a matter of fact, the code above only checks the existence of another object from the same class, it does not prohibit the creation of a new one)

hth
2008-05-05 04:20:56
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Автор:
A tricky way to implement Factory or Singleton is this one:
<?php

class {
   
// your amazing stuff
}

// implicit factory
function A/* one or more args */ ){
    return new 
A/* one or more args */ );
}

$a A(1,2,3);
$b A(2,3);

// or implicit Singleton
function A/* one or more args */ ){
    static 
$instance;
    return isset(
$instance) ? $instance : ($instance = new A/* one or more args */ ));
}

A(1,2,3) === A(2,3); // true
?>

More details in WebReflection, byez
2008-06-01 13:49:07
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Db layer design algorithm:
"Separation of database layer by database functionality"

First we draw this line:

Application
-------------
     DB

Here comes the new thing:
The db layer we separate it into two areas like this:

Db layer
       |
select | insert, update delete
       |

in the left side we have the select part.
The difference between the left and the right sides is that select side has no connection with the db structure - you can take data querying all table, while the right side is table oriented.

Select side:
Here all queries are in one file called "getters". Like getterUsers.

Inside it will be the body of the query but the fields that are to be selected will be build dynamically.
When calling this "getter" you will provide an array of fields to be selected or no fields, situation when it will take all fields.

To keep those db field names as low as possible in this architecture - so the above code dont need to know about the name of the fields in db, you will make just above this "getter", a "filter" file.
This filter will have a switch with a key and inside will call the getter with fields from db.
Ex:
<?php
switch(key)
case 
'Label':
$fields = array("label""firstName");
$obj->getUser($fields)
break;
?>

Above this filter you will have a "caller" that will call the "filter" with the key:
Ex:
<?php
function callerUserLabel()
{
->
filterUserLabel('Label');
}
?>

So in the higher code you just make
->callerUserLabel();
and this will return all what you need.

If you want this query to get out of the db and another field called "email", you just create another case in the switch and a "caller" to call that case.

Dynamic and extensible.

----------------

Now on the insert update side.
Here we only think in db tables.

First we do some "checkers" for all fields in db.
checkerTableName.php
This will contain an array with all the fields and the checks that must be done on that field and perform the checks only on the provided fields.

Then we do the "updaters". Those are build dinamically like the "getters" - if fields provided, only those updated. If all fields provided, can be used as an "inserter".

When performing an insert, all checks on that table will be done.

When performing an update on only one field - like updating a label, only that label will be checked to be in conformity with requirements like a length, special chars inside.
Dependency checks are made here also.

When having in one application action a multiple insert or update (when inserting an operator also add a webUser lets say) you do above those "inserter" and "updater" files a small "manager" that will do:
->checkOperatorFields();
->checkWebUserFields();

->insertOperator();
->insertWebUser();

If no error is thrown, all things will go nice and quiet.

Now also the "getters" will have their fields checked when needed using those checkers. I am talking about the values that are given as parameters not about the ones that are returned from db. 

If you are working with domain objects or business logic objects (whatever you call them) above the db layer you will have to make below that line we first draw a "business logic asambler" object that will make from your data what you want.

If this dont exist, at least an intermediary layer that will map the names from db with the ones used in application must be done in both directions - from application to db and from db to application.

-------------------------------------

Advantages of this architecture:
- Usefull in complex application especheally where the selects are made ussually from many tables so you dont have to load lots and lots of files and to get lost in the logic for one simple select.
- NO DUPLICATE CODE
- Simple and intuitive.
- Flexible and expendable.
2008-06-03 14:04:13
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Автор:
For quick instance access use function
<?php
class Example{....}

function 
Example {
  return 
Example::getInstance();
}

// Global access
Example()->sayHallo(...);
Example()->doSomething(...);
print 
Example()->someData;
?>
2008-08-27 10:05:27
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Автор:
I've been forward-developing for PHP 5.3, and couldn't help but notice that late-static-binding makes implementing Singletons simple. Its even easy to set up some function forwarding so that static calls are transformed into non-staic calls:

<?php
// Requires PHP 5.3!
class Singleton {
    public static function 
Instance() {
        static 
$instances = array();
       
$class get_called_class();
        if (!
array_key_exists($class$instances)) {
           
$instances[$class] = new $class();
        }
        return 
$instances[$class];
    }
    public static function 
__callStatic($func$args) {
       
$class = static::Instance();
        return 
call_user_func_array(array($class'__'.$func), $args);
    }
}

class 
Earth extends Singleton {
    public function 
__DoSomething($a$b) {
        return 
15 $this->SomethingElse($a$b);
    }
    protected function 
SomethingElse($c$d) {
        return 
$c $d;
    }
}

echo 
Earth::DoSomething(6,27);
?>
2008-09-06 21:49:37
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Автор:
The singleton effect you are applying to can be achieved in a old-fashioned and simpler way. Remember that the 'static' is the way for sharing the data between the objects from one type. And there is no pattern in this. So the only think you can do is to use the static keyword. If your program is already written and the rewrite is not recommended there is the "adapter pattern" witch can be used. It is intended to adapt an object to an already build environment. This is one way to have singleton functionality without actually the singleton pattern, it uses a class with static data and static methods and a adaptor class to adapt those methods to your interface.

The example shows how the every instance of the singlePoint class givs you the same data.
<?php
class single {
   
    static 
$a;
    static 
$b;
   
    protected static function 
_start($a,$b){
       
self::$a=$a;
       
self::$b=$b;
    }
    protected static function 
_get_a(){
        return 
self::$a;
    }
    protected static function 
_get_b(){
        return 
self::$b;
    }
}
class 
singlePoint extends single {
    public function 
__construct($a='',$b=''){
        if(
$a!='' && $b!=''){
           
single::_start($a,$b);
        }
    }
    public function 
get_a(){
        return 
single::_get_a();
    }
    public function 
get_b(){
        return 
single::_get_b();
    }
}

class 
scopeTest{
    public function 
__construct(){
       
$singlePointInstance = new singlePoint();
        echo 
'In scopeTest a='.$singlePointInstance->get_a().'<br />';
    }
}

$theSingle = new singlePoint(3,5);
echo 
'In index a='.$theSingle->get_a().'<br />';

$theScopeTest = new scopeTest();
?>

My point is that you don't need single instance of the class but you need access to the same data over and over again ant the build in way to do that in every language I know so far is the 'static' keyword. It was engineered to give you this functionality. All the singleton patterns and even this adapter is unnecessary complication of the structure. KISS = “Keep It Simple Stupid” no need of that!
2008-09-29 19:13:56
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Автор:
Let me describe another pattern it is called “Decorator”. It can be used to add features to already written object. It is useful for extending some library classes from your framework without changing the original classes (especially if somebody else wrote those). The actual meaning is best presented in an example.

<?php 
// the main interface in which we going to do some decoration
interface salad{
    public function 
wait();
}

// main class which is already defined and you can't or don't want to change
class shopSalad implements salad{
    private 
$tomatoes;
    private 
$cucumbers;
    private 
$cheese;
   
    public function 
__construct($tomatoes$cucumbers$cheese){
       
$this->tomatoes $tomatoes;
       
$this->cucumbers $cucumbers;
       
$this->cheese $cheese
    }
   
    public function 
wait(){
        echo 
"the salad is served using {$this->tomatoes} tomatoes, {$this->cucumbers} cucumbers and {$this->cheese} gr. of cheese.";
    }
}

// abstract decorator class - note that it implements salad
abstract class saladDecorator implements salad{
    protected 
$salad// the object for decoration
   
public function __construct(salad $salad){
       
$this->salad=$salad;
    }
   
// there is no need to mention the wait function therefore this class inherits the original salad
    // the purpose of this class is maintaining the type of the object produced by the decorators.
    // it inherits the same interface as the original and it will be inherited by the concrete decorators
}

// sauce decorator
class saladSauce extends saladDecorator {
    public function 
wait(){
       
$this->salad->wait();
        echo 
" Then it was decorated with some sauce.";
       
    }
}

// onions decorator
class saladOnions extends saladDecorator {
    public function 
wait(){
       
$this->salad->wait();
        echo 
" Then it was decorated with some onions.";
    }
}

$order1 = new shopSalad(2,1,100); // creates the salad in the normal way
$order1 = new saladSauce($order1); // add a decorator to the class
$order1->wait();
echo 
'<br />';

// or
$order3 = new saladOnions(new saladSauce(new shopSalad(1,0.5,50))); // you don't need to load a variable with the reference
$order3->wait();
?>

this will outputs:
the salad is served using 2 tomatoes, 1 cucumbers and 100 gr. of cheese. Then it was decorated with some sauce.
the salad is served using 3 tomatoes, 2 cucumbers and 100 gr. of cheese. Then it was decorated with some onions. Then it was decorated with some sauce.
the salad is served using 1 tomatoes, 0.5 cucumbers and 50 gr. of cheese. Then it was decorated with some souse. Then it was decorated with some onions.

The pattern is not intended to be used with simple object and I couldn't do more simple than that. The pattern is useful in every way when the extending of an object is required. It can be used to divide some methods from others or to create layers of interaction with the object. In example if you have an file interface and a imageFile class which implements the file and then you can have also an textFile for the textFile you can do some layering and if you want to read the file as XML you can mace a decorator to do so. The XML decorator will inherit the interface file so you can save it and    the instance of textFile will be given to create the decorator so you can read the actual text and pars it as XML. It is possible the file to be .ini or some other text based document and you can make a decorator for every one of them. This is the actual benefit of the pattern.
2008-09-29 20:44:59
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Till now writing singleton classes depends on making class constructor private or protected and that sounds good, but what if class constructor must be public (for example, a singleton class inherits from a non-singleton class which already has a public constructor). The way to do so is:

<?php
   
class nonSingleton
   
{
        protected 
$_foo;
       
        public function 
__construct($foo)
        {
           
$this -> _foo $foo;
        }
    }
   
    class 
Singleton extends nonSingleton
   
{
       
/**
         * Single instance of the class
         *
         * @var Singleton
         */
       
protected static $_instance NULL;
       
/**
         * A flag to know if we are in getInstance method or not.
         *
         * @var bool
         */
       
protected static $_withinGetInstance false;
       
       
/**
         * Public singleton class constructor
         *
         * @param mixed $foo
         */
       
public function __construct($foo)
        {
            if (! 
self :: $_withinGetInstance)
                throw new 
Exception('You cannot make a new instance of this class by using constructor, use getInstance() instead...');
           
parent :: __construct($foo);
           
/*
                Any other operations constructor should do...
            */
       
}
       
       
/**
         * Regular getInstance method
         *
         * @param mixed $foo
         * @return Singleton
         */
       
public static function getInstance($foo)
        {
           
self :: $_withinGetInstance true;
            if (! 
self :: $_instance)
               
self :: $_instance = new Singleton($foo);
           
self :: $_withinGetInstance false;
            return 
self :: $_instance;
        }
    }
?>
2008-10-13 04:59:52
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Автор:
1: The singleton pattern ensures that only one instance of a class is ever created. Thus, applying it to a database connection object is common, since reusing a connection reduces latency and slows down reaching the database server's connection limit. If a database connection is only made in the singleton's constructor then it is probably impossible to accidentally open another connection via that object.

I say "probably impossible" because there are still some other issues: in this example, an invalid database connection identifier can be stored, retrieved, or lost (since it is an unserializable resource type) via object serialization without careful attention to the __sleep and __wakeup magic methods (and probably won't be valid on deserialization even if it is retained), and the __clone magic method should be implemented in a way that prevents object duplication.

(This example also ignores database connection pooling to stay focused on singletons.)

2: A singleton does not contain itself; it contains a reference to itself, which is conceptually similar to a pointer from the C language or a reference from Java. (In fact these are all very different under the hood and in practice, but I will ignore this for simplicity.)

Consider the following typical PHP 5.0 to 5.2 implementation:

<?php
class Example {
   
    private static 
$instance;
   
    private 
__construct() {
       
// Do important initializations here, like normal.
   
}
   
    public static function 
getInstance() {
        if (
null == self::$instance):
           
// First invocation only.
           
$className __CLASS__;
           
self::$instance = new $className();
        endif;
        return 
self::$instance;
    }
   
    public function 
__clone() {
        throw new 
Exception('Illegally attempted to clone ' __CLASS__);
    }
}
?>

Static class member variables can exist even without an instance of their class, and static class methods can be invoked without a class instance as well. The member variable that holds a reference to the singleton class instance ($instance) is static, as is the method to instantiate a singleton object (Example::getInstance()). Note that the variable $instance is private, so it cannot be affected by anything external to the class (thus preventing outside code from creating an instance of Example).

Static member variables are not really "inside" a class; each class instance points to the same static member variables as other instances, "sharing" these static variables between them (in a way) even before any class instances exist. Thus, Example::getInstance() always checks the same $instance variable.

3: The constructor has an access specifier of "private" to prevent direct instantiation using the "new" operator. (Prior to the implementation of the __callStatic features of PHP 5.3 it is not useful to mark the constructor "protected" since subclasses won't automatically also be singletons.) However, private methods can be invoked from a class's other methods; the static method Example::getInstance() is therefore allowed to invoke the private constructor. On first invocation, it creates an instance of Example and stores a reference to it in $instance. Subsequently, it just returns this reference.

4: The singleton pattern makes a class (slightly) more complicated, and the overhead of invoking its instantiation method is probably slightly higher than accessing a global variable instead. However, the benefits are substantial from an architectural perspective: it helps prevent performance losses due to accidentally instantiating more than one heavyweight class, it helps prevent bugs due to accidentally instantiating more than one instance of a class (such as a class that renders the requested HTML document in an online content management system), and helps keeps your global namespace and other lexical scopes clean even prior to the introduction of proper namespaces in PHP 5.3 (thus helping to prevent accidental variable clobbering or unexpected initial variable values from a previous module).
2008-12-31 13:34:08
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Hello! I want to suggest another fast and universal way to create a singleton, that can store instances any class types. The idea based on php's ability to create object's properties in run time, and magic functions support. Main trick is to create not existed property in __get method and assign to it a value of new instance of class, named as property.

Code:

<?php 

class fClassOne
{

 public function 
get()
 {
  return 
"value 1<br>\n";
 }

 public function 
__construct()
 {
  echo 
"fClassOne constructed<br>\n";
 }

}

class 
fClassTwo
{

 public function 
get()
 {
  return 
"value 2<br>\n";
 }

 public function 
__construct()
 {
  echo 
"fClassTwo constructed<br>\n";
 }

}

class 
fSingleton
{
 public function 
__get($sClassName)
 {
  echo 
"isset check<br>\n";
  if(!isset(
$this->{$sClassName})) $this->{$sClassName} = new $sClassName;
  return 
$this->{$sClassName};
 }
}

$MySingleton = new fSingleton();

for (
$i 0$i 5$i++) echo $MySingleton->fClassOne->get();

echo 
$MySingleton->fClassTwo->get();
echo 
$MySingleton->fClassTwo->get();

 
?>

Output:

isset check
fClassOne constructed
value 1
value 1
value 1
value 1
value 1
isset check
fClassTwo constructed
value 2
value 2
2009-01-22 14:34:43
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Автор:
I think a simpler option is to have a loader class/object and then the actual class.  It keeps your class more secure in that you are defining the visibility on $instances and you keep your class neat and tidy.

I found this useful when trying to use the singleton method on a class that extends another class.

<?php

class module_loader {
    private static 
$instances;

    public static function 
getInstance($module_name) {
        if (!isset(
self::$instances[$module_name])) {
           
self::$instances[$module_name] = new $module_name();
        }

        return 
self::$instances[$module_name];
    }
}

class 
module_base {
   
proteced $name;

    public function 
__construct() {
       
// Do initialization stuff here

   
}

    public final function 
SomePermanentFunction() {
       
// Perform function actions
   
}
}

class 
module_test extends module_base {
    public 
$my_var;

    public function 
__construct() {
       
parent::__construct();

       
$this->name 'test';
       
$this->my_var '';
    }

    public function 
ModuleSpecificFunction() {

    }
}

?>

So then once you have all of that defined, you can then use it like such:

<?php

// Get first instance and set value
$instance1 module_loader::getInstance('module_test');
$instance1->my_var 'abc';

print 
"Instance 1 Var = " $instance1->my_var;

// Create second instance and check value
$instance2 module_loader::getInstance('module_test');

print 
"Instance 2 Var = " $instance2->my_var;

// Set value on second instance, check first instance
$instance2->my_var 'def';

print 
"Instance 1 Var = " $instance1->my_var;

?>

The output would then look like this:

Instance 1 Var = abc
Instance 2 Var = abc
Instance 1 Var = def

Thus $instance1 and $instance2 are created using the factory pattern but they both point back to the same object (singleton pattern).
2009-03-12 10:42:53
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Exemple of singleton that can be used for other class (need phpversion >= 5.3)
<?php
class SingletonModel
{
   
/**
     * Instance of singleton's class
     *
     * @var array
     */
   
private static $_instance;

   
/**
     * All constructeur should be protected
     */
   
protected function __construct(){}

   
/**
     * Singleton method to load a new object
     *
     * @return HlPwd_SingletonModel
     */
   
public static function singleton() 
    {
        if (!isset(
self::$instanceget_called_class() ]))
        {
           
$c get_called_class();
           
self::$instance = new $c;
        }
       
        return 
self::$instance;
    }

   
/**
     * Destroy the singleton
     */
   
public function destroySingleton()
    {
        unset(
self::$_instanceget_class($this) ]);
    }

   
/**
     * Destructeur
     */
   
public function __destruct()
    {
        unset(
self::$_instance);
    }

   
/**
     * Impeach the clone of singleton
     */
   
public function __clone()
    {
       
trigger_error('Cloning not allowed on a singleton object'E_USER_ERROR);
    }
}

# EOF

you can easyli use it  like that

class mySingChild extends SingletonModel
{
    protected function 
__construct()
    {
       
//do important things
   
}

    public function 
foo()
    {
        echo 
'hello world';
    }
}

$t mySingChild::singleton();
$t->foo();
2009-04-05 23:33:21
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Here's my singleton class for php 5.3.0:

<?php
class Singleton {
 
// this must be in every inherited singleton!
 
protected static $_instance;

 
// get the instance
 
final public static function instance() {
   
// create the instance if we don't have one
   
if (empty(static::$_instance)) {
     
$class get_called_class(); // php 5.3.0
     
static::$_instance = new $class;
    }

    return static::
$_instance;
  }

 
// must protect the constructor
 
protected function __construct() { }

 
// overload __clone
 
final public function __clone() {
    throw new 
Exception('Cannot duplicate a singleton.');
  }
}

// a sample extension
class Extension extends Singleton {
 
// has to be here, sadly... if only statics were inherited
 
protected static $_instance;

  protected function 
__construct() { ... }

  public function 
foo() {
    echo 
'foo\n';
  }
}

// example
$extension Extension::instance();
$extension->foo(); // echo's 'foo\n' as expected
?>

Having to add "protected static $_instance" to every singleton is somewhat annoying. I tried the obvious alternative and stored all the instances within an array in the Singleton class. I ran Extension::getInstance() 1,000,000 over 10 runs to see which method was faster:

Array of $_instances:  3.47s average
Individual $_instance: 1.75s average

Considering the array of instances only had 1 key to search through, it's reasonable to assume that method would get slower as singletons are added, whereas the method above will always stay the same speed. The difference was enough for me to suffer the minor inconvenience.
2009-04-17 12:56:45
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Ex.2 only makes a 'Singleton' in the sense there is only one object makable.
But! you can still assign the object to other names(like making aliases). Probably not 
what you usually want. Change the method a bit and you get only one unique name
for your 'Singleton'.. or else it will bark again and again!
<?php
#if you don't change example 2 you will get a $badDoggie
$badDoggie="I am constructedSorry but I'm already set.Sorry but I'm already set.
            Sorry but I'm already set.Woof!Woof!Woof!"
;
   
// The singleton method
   
public static function singleton() 
    {   
        if (!isset(
self::$instance)) {
           
$c __CLASS__;
           
self::$instance = new $c;
           
#return self::$instance;
       
}
        echo 
"Sorry but I'm already set.";
        return 
self::$instance##...wrong place for this!comment this, uncomment it above
   
}   
?>
<?php
// This would fail because the constructor is private
#$test = new Example;
// This will always retrieve a single instance of the class
$test Example::singleton();
$again Example::singleton();
$and_again Example::singleton();
$test->bark();
$again->bark();
$and_again->bark();
?>
2009-06-04 18:46:56
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Example of a decorator, which adds array access to any object:

<?php

class ArrayAccessDecorator implements ArrayAccess {
        protected 
$object null;
        public function 
__construct($object){
               
$this->object $object;
        }
        public function 
__call($method$args){
                return 
$this->productpart->$method($args);
        }
        public function 
__set($key$val){
               
$this->object->$key $val;
        }
        public function 
__get($key){
                return 
$this->object->$key;
        }
       
/* ArrayAccess */
       
public function offsetSet($key$value){
               
$this->__set($key$value);
        }
        public function 
offsetGet($key){
                return 
$this->__get($key);
        }
        public function 
offsetUnset($key){
               
$this->__set($keynull);
        }
        public function 
offsetExists($offset){

                       
$test $this->object->__get($offset);
                        if(
$test !== null){
                                return 
true;
                        } else {
                                return 
false;
                        }
        }
}

$stdobject = (object)array('test'=>'test''test2' => 'test2');
$arr = new ArrayAccessDecorator($stdobject);
print 
$arr['test']; // test
$arr['test'] = 'hello';
print 
$arr['test']; // hello
?>
2009-07-13 11:48:10
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
This class will let you chain objects together into a chain. You can forward a message into the chain. The message propagates upwards into the chain until an object can handle it and returns a value. Then the return value is send backwards into the chain until it reached the caller. 

This can be useful in various situations, where flexibility is needed. 

In the begin of the chain we put more specialized methods, which will handle special cases (like user defined objects, json code, xml etcetera). And in the back more general (strings, array's). Now we can pass data to the chain and always get valid and safe html back. If we encounter a new data type we just put on the head of the chain a new object, which can handle this type of data. 

<?php

abstract class Chainable {
        protected 
$next null;
        protected 
$prev null;
        protected 
$res null;

        public function 
forward(Message $object){
                if(
$return $this->run($object)){
                        return 
$this->backward($return);
                }
                if(
$this->next !== null){
                        return 
$this->next->forward($object);
                } else {
                        throw new 
Exception('No object can handle this type');
                }
        }
        public function 
backward(Message $object){
         
                if(
$this->prev === null){
                        return 
$object
                } else {
                        return 
$this->prev->backward($object);
                }
        }
        abstract public function 
run(Message $object);
        public function 
addLink(Chainable $link){
                if(
$this->next !== null){
                       
$this->next->addLink($link); 
                } else {
                       
$this->next $link;
                       
$this->next->setPrevLink($this);
                }
                return 
$this;
        }
        protected function 
setPrevLink(Chainable $link){
               
$this->prev $link;
                return 
$this;
        }
}
?>

Also needed the message object:

<?php
   
class Message {
        protected 
$data;
        public function 
__construct($data){
               
$this->data $data;
        }
        public function 
getMessage(){
                return 
$this->data;
        }
        public function 
setMessage($data){
               
$this->data $data;
        }
        public function 
__toString(){
                return (string)
$this->data;
        }
}

?>
2009-08-24 12:39:20
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
The Singleton class version wich is useable by only extending it :

you would use is for example like this :

<?php
class Users extends Singleton
{
   
// ...
   
public function SomeMethod()
    {
    }
}
?>

and in your code :

<?php
Users
::inst()->SomeMethod();
?>

I didn't check for performance, but here is the code :

<?php
class Singleton
{
   
// Hold an instance of the class
   
private static $instances = array();
   
   
// A private constructor; prevents direct creation of object
   
final private function __construct() 
    {
    }

   
// Prevent users to clone the instance
   
final public function __clone()
    {
       
trigger_error'Clone is not allowed.'E_USER_ERROR );
    }
   
   
// The singleton method
   
final public static function inst() 
    {
       
$c get_called_class();
       
        if( ! isset( 
self::$instances[$c] ) )
        {
           
self::$instances[$c] = new $c;
        }
       
        return 
self::$instances[$c];
    }
}
?>
2009-09-22 12:11:02
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
<?php
/**
 * Class Singleton is a generic implementation of the singleton design pattern.
 *
 * Extending this class allows to make a single instance easily accessible by
 * many other objects.
 *
 * @author     Quentin Berlemont <quentinberlemont@gmail.com>
 */
abstract class Singleton
{
   
/**
     * Prevents direct creation of object.
     *
     * @param  void
     * @return void
     */
   
protected function __construct() {}

   
/**
     * Prevents to clone the instance.
     *
     * @param  void
     * @return void
     */
   
final private function __clone() {}

   
/**
     * Gets a single instance of the class the static method is called in.
     *
     * See the {@link http://php.net/lsb Late Static Bindings} feature for more
     * information.
     *
     * @param  void
     * @return object Returns a single instance of the class.
     */
   
final static public function getInstance()
    {
        static 
$instance null;

        return 
$instance ?: $instance = new static;
    }
}
?>

E.g.

<?php
// Foo class
class Foo extends FrameworkCoreSingleton
{
   
// Bar method
   
public function bar()
    {
        echo 
__CLASS__ PHP_EOL;
    }
}

// Returns a single instance of Foo class
$foo Foo::getInstance();

// Prints: Foo
 
$foo->bar();
?>

Best regards,
Quentin.
2009-12-17 11:01:41
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Автор:
Php needs macros! That's right php seems almost unusable sometimes without precompiler. Fortunately you can generate php code with php and (easily) cache it so you can still take advantage of the php optimizing capabilities. It just creates a mess when debugging, no big deal ;)

You need to extend the language to your own needs.

But this singleton business might just work without without macros, not that nicely though.

<?php
class Singleton {
    private static 
$instance;
    public static function 
singleton($class __CLASS__) {
        if (!isset(
self::$instance))
           
self::$instance = array();
        if (!isset(
self::$instance[$classname]))
           
self::$instance[$classname] = new $classname;
        return 
self::$instance[$classname];
    }
}
class 
SubClass extends Singleton {
    public static function 
singleton($class __CLASS__) {
        return 
parent::singleton($class);
    }
}
class 
SubSubClass extends SubClass {
    public static function 
singleton($class __CLASS__) {
        return 
parent::singleton($class);
    }
}
?>

As you can see, the static $instance can be an associative array holding all the instances of derived classes, but you still can't work around overriding the singleton/getInstance static method... That's what macros or language extensions would be for...

<?php
class SINGLETON(SubClass) {
   
/*...*/
}
?>

Translate to:

<?php
class SubClass extends Singleton {
    public static function 
singleton($class __CLASS__) {
        return 
parent::singleton($class);
    }
   
/*...*/
}
?>
2010-03-05 09:11:06
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
Автор:
Singleton in php doesn't responded like java (or others), the static instance resets on every request......
2010-06-10 08:39:23
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
I've come up with an interesting and intuitive way to define a generic Factory class. It's basically an empty object that remembers all operations you perform on it. You can then request an actual instance, and all operations are repeated on that instance. The order of the operations is preserved.

<?php
   
# If you want a factory that initializes an object like this:
   
$myobject = new MyObject('arg1''arg2');
   
$myobject->doFooBar();
   
$myobject->baz 10;
   
   
# You write:
   
$f_myobject = new MagicFactory('MyObject''arg1''arg2');
   
$f_myobject->doFooBar();
   
$f_myobject->baz 10;

   
# You can now get the same object like this:
   
$myobject $f_myobject->instance();
?>

<?php
   
   
/**
     * Generic Factory class
     *
     * This Magic Factory will remember all operations you perform on it,
     * and apply them to the object it instantiates.
     *
     */
   
class MagicFactory {
        private 
$history$class$constructor_args;
       
       
/**
         * Create a factory of given class. Accepts extra arguments to be passed to
         * class constructor.
         */
       
function __construct$class ) {
           
$args func_get_args();
           
$this->class $class;
           
$this->constructor_args array_slice$args);
        }
       
        function 
__call$method$args ) {
           
$this->history[] = Array(
               
'action'    => 'call',
               
'method'    => $method,
               
'args'        => $args
           
);
        }
       
        function 
__set$property$value ) {
           
$this->history[] = Array(
               
'action'    => 'set',
               
'property'    => $property,
               
'value'        => $value
           
);
        }
       
       
/**
         * Creates an instance and performs all operations that were done on this MagicFactory
         */
       
function instance() {
           
# use Reflection to create a new instance, using the $args 
           
$reflection_object = new ReflectionClass$this->class ); 
           
$object $reflection_object->newInstanceArgs$this->constructor_args ); 
           
           
# Alternative method that doesn't use ReflectionClass, but doesn't support variable
            # number of constructor parameters.
            //$object = new $this->class();
           
            # Repeat all remembered operations, apply to new object.
           
foreach( $this->history as $item ) {
                if( 
$item['action'] == 'call' ) {
                   
call_user_func_array( Array( $object$item['method'] ), $item['args'] );
                }
                if( 
$item['action'] == 'set' ) {
                   
$object->{$item['property']} = $item['value'];
                }
            }
           
           
# Done
           
return $object;
        }
    }
   
?>

Example:

<?php
   
   
class Person {
        private 
$name$sirname;
        public 
$age;
       
        function 
__construct$name$sirname ) {
           
$this->name $name;
           
$this->sirname $sirname;
        }
       
        function 
setName$name ) {
           
$this->name $name;
        }
       
        function 
introduce() {
            print 
"Hello, my name is {$this->name} {$this->sirname}! I'm {$this->age} years old.";
        }
    }
   
   
# Setup a factory
   
$person_factory = new MagicFactory('Person''John''Johnson');
   
$person_factory->setName('Jack');
   
$person_factory->age 55;
   
   
# Get an instance
   
$jack $person_factory->instance();
   
$jack->introduce();
   
   
# Prints:
    # Hello, my name is Jack Johnson! I'm 55 years old
2010-08-18 05:05:44
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
It is possible to use every class 
as if it is a singleton with a little abstraction.

I wrote some code to show you:

<?php
 
class MyEngine/* static */
   
static $singletons=array();
    static function 
singletonizer($classname,$classarguments=array()){
     
$sca=serialize($classarguments);
      if (!isset(
MyEngine::$singletons[$classname][$sca])) {
        if (!
class_exists($classname)) 
         
/* auto loader, add error reporting for missing classes etc */
         
include("classes/".$classname."/.class.php");
       
MyEngine::$singletons[$classname][$sca]
          =& new 
$classname($classarguments);
      }
     
/* this is the pointer/reference and not a new object! */
     
return MyEngine::$singletons[$classname][serialize($classarguments)];
    }
    static function 
debug($msg,$data=""){
      echo 
"<pre>".$msg."\t".print_r($data,1)."</pre>\r\n";
    }
  }
?>   

Now let's test it!
Defining a class:

<?php
 
class testclass{
    private 
$value;
    function 
__construct($args){
     
MyEngine::debug("- testclass contructed with ",$args);
      if (isset(
$args["value"]))
       
$this->set($args["value"]);
      else
       
$this->value=0;
    }
    public function 
set($value){
     
$this->value $value;
     
MyEngine::debug("- testclass set value =",$this->value); 
    }
    public function 
get(){
     
MyEngine::debug("- testclass get value =",$this->value);
      return 
$this->value;
    }
  }
?>

And here we run a testcase:

<?php
  $args
=array("value"=>12);
 
MyEngine::debug('create $a','expecting: contruct and set 12');
 
$a=MyEngine::singletonizer("testclass",$args); 
 
$a->set(13);
 
MyEngine::debug('create $b','expecting: just load it. should be 13, no contruct');
 
$b=MyEngine::singletonizer("testclass",$args); 
 
MyEngine::debug("b value is (expecting 13)",$b->get());
 
$args=array("value"=>11);
 
MyEngine::debug('create $c','different args -> new construct, set 11');
 
$c=MyEngine::singletonizer("testclass",$args); 
 
MyEngine::debug("c value is (expecting 11)",$c->get());
 
$args=array("value"=>12);
 
MyEngine::debug('create $d','recognize args, load it, should be 13');
 
$d=MyEngine::singletonizer("testclass",$args);
 
MyEngine::debug("d value is (expecting 13)",$d->get());
?>

feedback welcome!

HTH :)

Patrick from Berlin, Germany
2011-02-24 12:42:58
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html
This is a simple Command Pattern example which performs Undo operation on a calculator. You may use callbacks in order to verify open-close principle.
<?php
abstract class Command {
    abstract public function 
unExecute ();
    abstract public function 
Execute ();
}
class 
concreteCommand extends Command {
    private 
$operator,$operand,$calculator;
    public function 
__construct ($calculator,$operator,$operand) {
       
$this->operator $operator;
       
$this->operand $operand;
       
$this->calculator $calculator;
    }
    public function 
Execute() {
       
$this->calculator->Action($this->operator,$this->operand);
    }
    public function 
unExecute () {
       
$this->calculator->Action($this->Undo($this->operator),$this->operand);
    }
    private function 
Undo ($operator) {
        switch (
$operator) {
            case 
'+': return '-';
            case 
'-': return '+';
            case 
'*': return '/';
            case 
'/': return '*';
        }
    }
}
class 
Calculator {
    private 
$current;
    public function 
__construct() {
       
$this->current 0;
    }
    public function 
Action($operator,$operand) {
        switch (
$operator) {
            case 
'+':
               
$this->current += $operand;
                break;
            case 
'-':
               
$this->current -= $operand;
                break;
            case 
'*':
               
$this->current *= $operand;
                break;
            case 
'/':
               
$this->current /= $operand;
                break;
        }
    }
    public function 
getCurrent() {
        return 
$this->current;
    }
}
class 
Invoker {
    private 
$commands,$calculator,$current;
    public function 
__construct() {
       
$current =-1;
    }
    public function 
Undo() {
        if (
$this->current >= 0) {
           
$this->commands[$this->current]->unExecute();
           
$this->current--;
        }
    }
    public function 
Compute($command) {
       
$command->Execute();
       
$this->current++;
       
$this->commands[$this->current] = $command;
    }
}

?>

Example Usage:

<?php
$User 
= new Invoker();
$calculator = new Calculator();
$command = new concreteCommand($calculator,'+',5);
$User->Compute($command);
echo 
"After +5: ".$calculator->getCurrent()."<br/>";
$command = new concreteCommand($calculator,'*',7);
$User->Compute($command);
echo 
"After *7: ".$calculator->getCurrent()."<br/>";
$command = new concreteCommand($calculator,'/',2);
$User->Compute($command);
echo 
"After /2: ".$calculator->getCurrent()."<br/>";
$command = new concreteCommand($calculator,'-',10);
$User->Compute($command);
echo 
"After -10: ".$calculator->getCurrent()."<br/>";
$User->Undo();
echo 
"Undo Operation: ".$calculator->getCurrent()."<br/>";
$User->Undo();
echo 
"Undo Operation: ".$calculator->getCurrent()."<br/>";
$User->Undo();
echo 
"Undo Operation: ".$calculator->getCurrent()."<br/>";
$User->Undo();
echo 
"Undo Operation: ".$calculator->getCurrent()."<br/>";
?>

and Output:

After +5: 5
After *7: 35
After /2: 17.5
After -10: 7.5
Undo Operation: 17.5
Undo Operation: 35
Undo Operation: 5
Undo Operation: 0
2011-12-03 17:05:19
http://php5.kiev.ua/manual/ru/language.oop5.patterns.html

    Поддержать сайт на родительском проекте КГБ