Padrões (Patterns) são formas de descrever melhores práticas e bons projetos. Eles mostram soluções flexíveis para problemas comuns de programação.
O padrão Factory permite a instanciação de objetos em tempo de execução. É chamado de Factory uma vez que é responsável por "produzir" um objeto. O Factory parametrizado recebe como argumento o nome da classe para instanciar.
Exemplo #1 Método Factory Parametrizado
<?php
class Exemplo
{
// Método Factory parametrizado
public static function factory($type)
{
if (include_once 'Drivers/' . $type . '.php') {
$classname = 'Driver_' . $type;
return new $classname;
} else {
throw new Exception ('Driver não encontrado');
}
}
}
?>
Definir esse método numa classe permite que drivers sejam carregados em tempo de execução. Se a classe Exemplo fosse uma classe de abstração de banco de dados, carregar um driver MySQL e um driver SQLite poderia ser feito como se segue:
<?php
// Carregar um driver MySQL
$mysql = Exemplo::factory('MySQL');
// Carregar um driver SQLite
$sqlite = Exemplo::factory('SQLite');
?>
O padrão Singleton se aplica em situações em que é preciso haver uma só instância de uma classe. O exemplo mais comum é uma conexão com um banco de dados. Implementar esse padrão permite ao programador fazer essa instância única ser facilmente acessível por muitos outros objetos.
Exemplo #2 Função Singleton
<?php
class Exemplo
{
// Guarda uma instância da classe
private static $instance;
// Um construtor privado; previne a criação direta do objeto
private function __construct()
{
echo 'Sou um construtor';
}
// O método singleton
public static function singleton()
{
if (!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
// Método exemplo
public function latir()
{
echo 'Au!';
}
// Previne que o usuário clone a instância
public function __clone()
{
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
}
?>
Isso permite que uma instância única de Exemplo seja recuperada.
<?php
// Isso falharia porque o construtor é privado
$test = new Exemplo;
// Isso sempre vai recuperar uma instância da classe
$test = Exemplo::singleton();
$test->latir();
// Isso irá emitir um E_USER_ERROR.
$test_clone = clone $test;
?>