Conexão com banco de dados implementando Abstract Factory – PHP

Bom, nessa postagem vou mostrar um exemplo de conexão com o banco de dados implementando o pattern Abstract Factory.

Com esse pattern, é possível fazer alterações no sistema sem precisar de grandes mudanças, apenas, digamos, instanciar um objeto no lugar de outro, tendo uma família de objetos que trabalham de forma transparente. Por exemplo: você tem uma aplicação com banco de dados MySQL, mas você decide trocar de SGBD, para um PostgreSQL. O que fazer? Alterar todo o código de conexão para as necessidades do PostegreSQL? Não! Com esse pattern você só precisa mudar a instância de MySQL para PostgreSQL. Vamos à implementação? Bem, a conexão de cada banco é parecida, então podemos criar uma classe abstrata pra isso:

abstract class AbstractConnectorConfig{
    private $host;
    private $dbname;
    private $user;
    private $password;

    public function __construct( $host, $dbname, $user, $password ){
        $this->host = $host;
        $this->dbname = $dbname;
        $this->user = $user;
        $this->password = $password;
    }

    public function getHost(){
        return $this->host;
    }

    public function getDbname(){
        return $this->dbname;
    }

    public function getUser(){
        return $this->user;
    }

    public function getPassword(){
        return $this->password;
    }

    abstract public function getDsn();
}

Agora para uma configuração de conexão com MySQL:

class MySQLConnectorConfig extends AbstractConnectorConfig{
    public function getDsn(){
        return sprintf( 'mysql:host=%s;dbname=%s',
            $this->getHost(),
            $this->getDbname() );
    }
}

e para PostgreSQL:

class PostgreSQLConnectorConfig extends AbstractConnectorConfig{
    public function getDsn(){
        return sprintf( 'pgsql:host=%s;dbname=%s',
            $this->getHost(),
            $this->getDbname() );
    }
}

Mas para conexão também é necessário um conectador:

interface Connector{
    public function connect( AbstractConnectorConfig $connectorConfig );
    public function disconnect();
    public function isConnected();
    public function getConnection();
}

O principal do PHP é o PDO, então:

class PDOConnector implements Connector{
    private $instance;

    public function __construct( AbstractConnectorConfig $connectorConfig ){
        $this->connect( $connectorConfig );
    }

    public function connect( AbstractConnectorConfig $connectorConfig ){
        if( !$this->isConnected() ){
            $this->instance = new PDO( $connectorConfig->getDsn(),
                $connectorConfig->getUser(),
                $connectorConfig->getPassword() );
            $this->instance->setAttribute( PDO::ATTR_ERRMODE,
                    PDO::ERRMODE_EXCEPTION );
    }
}

    public function disconnect(){
        if( $this->isConnected() ){
            $this->instance = null;
    }
}

    public function isConnected(){
        return ( $this->instance instanceof PDO );
    }

    public function getConnection(){
        return $this->instance;
    }
}

E a implementação fica muito mais simples:

$connector_config = new MySQLConnectorConfig( 'localhost',
                                              'dbname',
                                              'root',
                                              '' );

$connector = new PDOConnector( $connector_config );

e se quiser mudar pra PostgreSQL:

$connector_config = new PostgreSQLConnectorConfig( 'localhost',
                                                   'dbname',
                                                   'root',
                                                   '' );

$connector = new PDOConnector( $connector_config );

Conclusão:

Viram? O código não sofre quase que nenhuma modificação! E o conectador não sabe nem em que banco está se conectando.

Para se aprofundar mais sobre este pattern e muitos outros, aconselho o livro Head First – Design Patterns.

Comente