Implementation of Abstract Factory, Factory Method and Adapter standards

Asked

Viewed 336 times

3

I read the following sentence: 

Abstractfactory defines an interface for creating a family of related or dependent products without you having to explicitly specify the 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);
    }
}

Note that this class has the method factory which returns the instance of a new class according to the settings file:

Config.ini

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

I used the standard Factory Method for knowing which class should be used only at the time of script execution. Note that in the settings file there is a setting:

db = MySQL

With this the adapter will generate an instance of the class DbAdapterMySQL (actually the class is kind of 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
    }
}

Note 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();

I can say I used the standards Adapter, Factory Method and Abstract Factory in the above classes?

  • The pattern Adapter because I used the class DbAdapterMySQL to build an application-compatible interface, so when I switch from Mysql to MSSQL I only have to create a new class DbAdapterMSSQL and implement their methods.
  • The pattern Factory Method because I used the method factory class Adapter to return an instance of the class that must be used (at runtime) according to the project settings.
  • And here is my question, I can say I used the standard Abstract Factory? Once I used the interface DbInterface for the creation of a family of related products, which in this case is for handling the DBMS?

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

  • Related: http://answall.com/q/157466/101

1 answer

2

Hello, I am not an expert in php, but I could understand your question well.

My first observation is about you using the Abstract Factory, I don’t really see you employing the same, because as you quoted:

Since I used the Dbinterface interface interface for creating a family of related products, which in this case is for handling the DBMS

Here we can observe 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 case instances for the database.

We could consider a family for example if you had something like that:

<?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 ended up in the structural pattern Bridge.

Why this vision of mine?

On the website making source is very clear the definition of this pattern. Below 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.

  • Publish interface in an inheritance Hierarchy, and Bury implementation in its Own inheritance Hierarchy.

  • Beyond Encapsulation, to Insulation

And basically what you did was take such advantage of Adapter, since you are structuring your application so that "incompatible" banks can be used through a single perspective in your code, when the Bridge, where its Adapter abstraction, which provides the Factory to the database, can vary independently as far as the Dbinterface implementations that runs its commands in the database.

I hope my vision can help you.

  • @Filipemoraes here you will see a very cool example of the family concept within Abstract Factory.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.