Implementation of Abstract Factory, Factory Method and Adapter standards

3

I have read the following sentence:

  

AbstractFactory defines an interface for creating a family of related or dependent products without having to explicitly specify classes.

Consider the following adapter:

Adapter.php     

namespace Teste\Db;

use Teste\Db\Adapter\DbInterface;

class Adapter
{
    private $config = null;

    public function __construct(array $config)
    {
        $this->config = $config;
    }

    public function factory()
    {
        $db = $this->config['db'];

        $class = __NAMESPACE__ . '\Adapter\DbAdapter' . $db;

        return new $class($this->config);
    }
}

Notice that this class has the factory method that returns the instance of a new class as per the configuration file:

Config.ini

db = MySQL
dbname = fixeads
username = 'root'
passwd = 'root'
host = localhost
debug = true

I used the Factory Method pattern because it knows which class should be used only at run time of the script. Notice that in the configuration file there is a definition:

db = MySQL

With this the adapter will generate an instance of class DbAdapterMySQL (actually the class is of type DbInterface , see below):

<?php

namespace Teste\Db\Adapter;

use Teste\Util\Iterator\Collection;

class DbAdapterMySQL extends \PDO implements DbInterface
{
    public function __construct(array $config)
    {
        $dsn = "mysql:dbname={$config['dbname']};host={$config['host']}";
        parent::__construct($dsn, $config['username'], $config['passwd']);

        $this->setAttribute(self::ATTR_DEFAULT_FETCH_MODE, self::FETCH_ASSOC);
    }

    public function insert($table, array $fields)
    {
       //inserir
    }

    public function select($table, $cols = '*', $where = [])
    {
        //selecionar
    }

    public function getFields($table)
    {
        //descrição dos campos
    }
}

Notice that the class implements the interface DbInterface :

<?php

namespace Teste\Db\Adapter;

interface DbInterface
{
    public function __construct(array $config);
    public function select($table, $cols = '*', $where = null);
    public function insert($table, array $fields);
    public function getFields($table);
}

And to use everything I do the following:

$config = parse_ini_file(sprintf(__DIR__ . '%sconfig.ini', DIRECTORY_SEPARATOR));
$dbAdapter = new DbAdapter($config);
Mapper::$defaultAdapter = $dbAdapter->factory();

Can I say that I used the Adapter , Factory Method and Abstract Factory

  • The Adapter pattern because I used the DbAdapterMySQL class to build an application-compatible interface, so when switching from MySQL to MSSQL I just have to create a new DbAdapterMSSQL class and implement the respective methods.
  • The Factory Method default because I used the factory method of the Adapter class to return an instance of the class that should be used (at runtime) according to the project settings.
  • And here is my question, can I say that I used the Abstract Factory pattern? Since I've used the DbInterface interface to create a family of related products, which in this case is for handling the DBMS?

If yes, then the Adapter class together with the DbInterface and DbAdapterMySQL classes are the implementation of the Abstract Factory pattern?

    
asked by anonymous 28.02.2017 / 21:43

1 answer

2

Hello, I'm not an expert in php, but I can understand your question well.

My first comment is that you are using abstract factory , I do not actually see you using it, as you mentioned:

  

Since I used the DbInterface interface to create a family of related products, which in this case is for handling the DBMS

Here we can see that you are not providing creation for an entire family of products. In fact, you are only in charge of providing the instance of a single product, in this case instances for the database.

We could consider a family for example if you had something of the sort:

<?php

 namespace Teste\Db\Adapter;

class Adapter
{
    private $config = null;

    public function __construct(array $config)
    {
       $this->config = $config;
    }

    public function factoryBancoRelacional()
    {
    }
    public function factoryBancoNaoRelacional()
    {
    }
}

Note the difference, you have a class responsible for returning different types of banks, which are incompatible with each other, but belong to the same family of Database Managers , different from the previous model where you have a class that will always return you an instance of a single product type, a relational database.

With that in mind, I see that with the sum of these patterns you have ended up in the structural Bridge pattern.

Why this my vision?

On source making the definition of this pattern becomes clear. Here are some of the rules that define it:

  

Adapter makes things work after they're designed; Bridge makes them work before they are.

     
  • Decouple an abstraction from its implementation so that the two can vary independently.

  •   
  •   
  • Beyond encapsulation, to insulation

  •   

And basically what you did was take advantage of both Adapter , since you is designing your application so that "incompatible" banks can be used through a single perspective in your code, when Bridge < a> , where your Adapter abstraction, which provides the factory for the database, can vary independently as far as the implementations of DbInterface that executes your commands in the database.

I hope that my vision can help you.

    
06.03.2017 / 18:57