Use interfaces to abstract connection type

3

In college we learn to use the FACTORY template for connections, but I wonder if it is possible to apply interfaces as well, as in the following example:

Case study

I have an application in php that follows as closely as possible the MVC pattern, but that should have the connection independent, that is, if it is necessary to change the bank, there was no need to rewrite the whole application.

Then, a class named MySQ_LConnect was created in the model, which provides connection to the Mysql database, as well as the execution of the querys that is passed to it:

class MYSQL_connect {

    private $hostname = 'myHost';
    private $username = 'DBUser';
    private $senha = '';
    private $banco = 'database';
    private $conn;

    public function conectar(){
        $this->conn = mysql_pconnect($this->hostname, $this->username, $this->senha);
        $db = mysql_select_db($this->banco,$this->conn);
        return $this->conn;
    }

    public function executarQuery($query,$conn){
        $result = mysql_query($query,$conn);
        return $result;
    }

    public function desconectar($conn){
        mysql_close($conn);
    }

Considering a future migration to sql server , a connection class was created for this bank and an interface, just to parameterize the two existing connection classes:

Interface

interface iConnect{

    public function conectar();
    public function executarQuery($query,$conexao);
    public function desconectar($conexao);
}

Connection class with sqlserver

class MSSQL_connect implements iConnect{

    private $hostname = 'myHost';
    private $connInfo = array("Database"=>"database", "UID"=>"DBUser", "PWD"=>"");
    private $conn;

    public function conectar(){
        $this->conn = sqlsrv_connect($this->hostname, $this->connInfo) or die(sqlsrv_errors());
        return $this->conn;
    }

    public function executarQuery($sql,$conn){
        $result = sqlsrv_query($conn,$sql,array(),array("Scrollable"=>"buffered"));
        return $result;
    }



    public function desconectar($conn){
        sqlsrv_close($conn);
    }
}

Note: in class MYSQL_connect the interface has been implemented too.

Then, in the test environment, you can switch between banks using a Fabrica connection, where BANCO is a prefix of banks (just to make it easier to switch between banks):

require_once 'MySQL_connect.php';
require_once 'MSSQL_connect.php';
define("BANCO","MySQL");//ou pode ser MSSQL
    class Fabrica{

        public function fabricar(){
            $classeDAO  = BANCO."_connect";

            return new $classeDAO;
        }       
    }

Doubt

How to use interfaces in this case to abstract the connection type, similar to what the Fabrica class is trying to do, so that for the rest of the application it makes no difference what bank is connecting to?

If the interface does not meet this requirement well, how to abstract without using Factory ?

    
asked by anonymous 26.11.2015 / 11:18

3 answers

1

One way to do this would be like this:

interface InterfaceFabrica {

   public function __construct(DatabaseConnect $databaseConnect);

}

It would have a class for the type as dependency injection:

class DatabaseConnect {

    const TYPE = 'MySQL';

    public function __construct($type = self::TYPE) {
        $classeDAO = $type. "_connect";
        return new $classeDAO;
   }

}

And the factory class deployed with its manufacturing interface:

class Fabrica implements InterfaceFabrica {

   public function __construct(DatabaseConnect $databaseConnect) {
       return $this;
   }
}

Forcing the type to pass through a constant, initiating fabrication through the constructor:

define('DATABASE_TYPE', 'MySQL');

$databaseConnect = new DatabaseConnect(DATABASE_TYPE);

$fabrica = new Fabrica($databaseConnect);
    
05.01.2016 / 15:04
1

I suggest only an improvement, in class Fabrica , to use class constants:

class Fabrica {

    const TIPO_MYSQL = 'MySQL';
    const TIPO_MSSQL = 'MSSQL';

    public function fabricar($banco = self::TIPO_MYSQL) {
        $classeDAO  = $banco . "_connect";
        return new $classeDAO;
    }

}
    
26.11.2015 / 12:27
1

In order to create a factory, an interface is not necessary, interfaces are only consistent. One of the main priorities of this standard, if I may say so, is to create objects without having to specify the exact class. They are useful when you want to use completely different objects in the same way. That is, different logics, but the same behavior when applied.

<?php

namespace Build;

class Forma
{
    public static function getForma($forma, $area)
    {
        switch($forma):
            case 'circulo';
                return new Circulo($area);
            case 'quadrado':
                return new Quadrado($area);
            default:
                return new stdClass();          
        endswitch;  
    }
    public function getArea()
    {
        // return get_class($this)
        return $this->getArea();
    }
}

class Circulo extends Forma 
{
    private $area;
    public function __construct($area)
    {
        $this->area = $area;
    }
    public function getArea(){
        return M_PI * ($this->area)**2;
    }
}

class Quadrado extends Forma 
{
    private $area;
    public function __construct($area)
    {
        $this->area = $area;
    }
    public function getArea()
    {
        return ($this->area)**2;
    }
}

?>

In this example, the circulo and quadrado classes are derived from the forma class, and have the same methods, but are different in logic, but still produce the same result, which is to return the corresponding area. It is on this principle that you should start working in factories.

<?php

include_once 'class.forma.php';

$forma = \Build\Forma::getForma('circulo', 3);
print $forma->getArea();
print "<br/>";
$forma = \Build\Forma::getForma('quadrado', 4);
print $forma->getArea();
print "<br/>";

?>

See the example .

Another rich example is this , with the use of interfaces, where the Sedan factory can produce different models of the same brand, using the same processes. This should be your starting point.

    
26.11.2015 / 14:04