Xwab
Форумыnavigate_nextПрограммирование на PHP

Паттерны проектирования(Factory, Singleton, Facade и Registr
Сообщения
manyrus

Захотелось почитать доп. литературы, а не крутиться вокруг mvc.
Сегодня я рассмотрел 4 паттерна:
1).Factory
2).Singleton
3).Facade
4).Registry

Factory
Паттерн Factory нужен для того, чтобы обеспечить слабое связывание между объектами. Он позволяет создавать целые группы взаимосвязанных объектов, которые, будучи созданными одной фабрикой, реализуют общее поведение.
Пример кода:

<?php
abstract class GUIFactory {
    public static function getFactory() {
        $sys = substr(PHP_OS, 0, 3);
        if (strtoupper($sys) === 'WIN') {
            return(new WinFactory());
        } else {
            return(new LinFactory());
        }
    }
    public abstract function createButton();
}
 
class WinFactory extends GUIFactory {
    public function createButton() {
        return(new WinButton());
    }
}
 
class LinFactory extends GUIFactory {
    public function createButton() {
        return(new LinButton());
    }
}
 
abstract class Button {
    private $_caption;
    public abstract function render();
 
    public function getCaption(){
        return $this->_caption;
    }
    public function setCaption($caption){
        $this->_caption = $caption;
    }
}
 
class WinButton extends Button {
    public function render() {
        return "Я WinButton: ".$this->getCaption();
    }
}
 
class LinButton extends Button {
    public function render() {
        return "Я LinButton: ".$this->getCaption();
    }
}
 
$aFactory = GUIFactory::getFactory();
$aButton = $aFactory->createButton();
$aButton->setCaption("Пуск");
echo $aButton->render();
?>
Этот код не использует интерфейсы, вместо них абстракция.

А вот и код с использованием интерфеса:
interface Input{
    public function input($file, $value);
}

class MultiLineInput implements Input{
    public function input($file, $value=array()) {
        $r="";
        foreach($value as $name=>$v) {
            $r.='['.$name.']='.$v."\n\r";
        }
        file_put_contents($file, $r);
    }
}

class InLineInput implements Input{
    public function input($file, $value) {
        file_put_contents($file, $value."\n\r");
    }
}

class InputStr {
    public static function Input($type, $value, $file){
        $input = InputStr::GetInput($type);

        $input->input($file, $value);

    }

    private static function GetInput($type) {
        if($type=="array") {
            return new MultiLineInput();
        } if($type="line") {
            return new InLineInput();
        }
    }
}

InputStr::Input("array",array("test"=>"test"), "new2");
Конечно на реализацию этого паттерна уходит достаточно много времени, но поверьте, оно того стоит

Singleton
Этот паттерн обеспечивает, что данный класс будет инициализирован всего лишь 1 раз.

Пример кода, тут достаточно всё легко:

class Singleton
{
    private static
        $instance = null;
 
    /**
     * @return Singleton
     */
   
    public static function getInstance()
    {
        if (null === self::$instance)
        {
            self::$instance = new self();
        }
 
        return self::$instance;
    }
 
    private function __clone() {}
    private function __construct() {}
   
 
 
    public function test()
    {
        var_dump($this);
    }
}
 
$Object = Singleton::getInstance();  // Получение объекта
 
//Вывод будет одинаковым, так как существует только один экземпляр
$Object -> test();
Singleton::getInstance() -> test();
 
// Попытка создать дополнительный экземпляр приведет к ошибке
$Object2 = new Singleton(); // Fatal error: Call to private Singleton::__construct() from invalid context
$Object3 = clone $Object; // Fatal error: Call to private Singleton::__clone() from context ''


Facade
Этот паттерн создан для того, чтобы скрыть сложные части путём сведения всех возможных вызовов в один объект.

Код достаточно лёгок, да и Вы, наверное, не раз его использовали

/* Сложные части системы */
class CPU
{
    public function freeze() { /* ... */ }
    public function jump( $position ) { /* ... */ }
    public function execute() { /* ... */ }
 
}
 
class Memory
{
    public function load( $position, $data ) { /* ... */ }
}
 
class HardDrive
{
    public function read( $lba, $size ) { /* ... */ }
}
 
/* Фасад */
class Computer
{
    protected $cpu = null;
    protected $memory = null;
    protected $hardDrive = null;
 
    public function __construct()
    {
        $this->cpu = new CPU();
        $this->memory = new Memory();
        $this->hardDrive = new HardDrive();
    }
 
    public function startComputer()
    {
        $this->cpu->freeze();
        $this->memory->load( BOOT_ADDRESS, $this->hardDrive->read( BOOT_SECTOR, SECTOR_SIZE ) );
        $this->cpu->jump( BOOT_ADDRESS );
        $this->cpu->execute();
    }
}
 
/* Клиентская часть */
$facade = new Computer();
$facade->startComputer();

Registry(реестр)
Этот паттерн создан для того, чтобы организовать глобальное хранилище(типа $_GLOBALS()) с единственной точкой доступа.

Реализация этого паттерна проста.
class SingletonRegistry
{
        /**
         * Static instance
         *
         * @var SingletonRegistry
         */
        private static $_instance;
        /**
         * Object hash map
         *
         * @var array
         */
        private $_map;
        /**
         * Private constructor
         *
         */
        private function __construct()
        {}
        /**
         * Get the single instance
         *
         * @return SingletonRegistry
         */
        public static function getInstance()
        {
                if(self::$_instance === null)
                {
                        //First and only construction.
                        self::$_instance = new self();
                }
                return self::$_instance;
        }
        /**
         * Get an object by key
         *
         * @param string|int $key
         * @return object
         */
        public function get($key)
        {
                return $this->_map[$key];
        }
        /**
         * Set an object by key
         *
         * @param string|int $key
         */
        public function set($key, $object)
        {
                return $this->_map[$key] = $object;
        }
        /**
         * Disallow cloning
         *
         */
        private function __clone()
        {}
}

На сегодня всё, спасибо за внимание.
P.s.: могут быть опечатки, прошу сообщить о них.

Источники
1). http://goo.gl/Cv0El
2). http://goo.gl/GXh3s
3). http://goo.gl/synqs
4). http://www.interface.ru/home.asp?artId=21133
5). http://dron.by/post/pattern-proektirovaniya-singleton-odinochka-na-php/
5). http://www.phparticles.ru/php/shablony-proektirovaniya-singleton-i-singleton-registry.html
6). http://i-novice.net/shablon-proektirovaniya-reestr/

26 Дек 2010, 17:39
suhonok

Ы, недоглядел


__________
посл.ред. 26 Дек 2010, 20:21; всего 1 раз 26 Дек 2010, 20:07
manyrus

SingletonRegistry::getInstance()->get("name");

26 Дек 2010, 20:13
iceman12

Никогда не понимал зачем нужен Singleton >_<. Это защита от того, чтобы не вызывать какой-то класс повторно? О.о

26 Дек 2010, 22:19
OZ_

iceman12, иногда и статическим классам требуется событие инициализации (которое обычно в конструкторе).

26 Дек 2010, 22:32
manyrus

Вообще, поидее, registry нужно для хранение данных(текст, к примеру), синглтон-для того, чтобы объект был доступен отовсюду.

26 Дек 2010, 23:20
manyrus

Тойсть если в registry положить объект, это будет не практично, т.к. у singleton не будут выпадать подсказки, к примеру.


Singleton::getInstance()-> выпадет test(), если использовать наш пример.

Ещё плюс в том, что он предоставляет глобальную точку доступа и больше возможностей.


__________
посл.ред. 26 Дек 2010, 23:36; всего 3 раз(а) 26 Дек 2010, 23:21
OZ_

manyrus, с чего бы вдруг?
прежде, чем копипастить, стоит обдумывать самому.

26 Дек 2010, 23:22
manyrus

OZ_, #5, он нужен только для того, чтобы объект был доступен ото всюду.Ну и он даёт больше возможностей, т.к. работает с экземпляром класса.

26 Дек 2010, 23:34
OZ_

manyrus, я про другое спрашивал.
С чего ты взял, что в реестрах не хранят объекты?

26 Дек 2010, 23:50
Ответить на тему