Skip to content

Latest commit

 

History

History
166 lines (119 loc) · 4.23 KB

File metadata and controls

166 lines (119 loc) · 4.23 KB

Design Pattern - Factory

La Fabrique est un patron de conception de création qui permet de créer des produits sans avoir à préciser leurs classes concrètes.

La fabrique définit une méthode qui doit être utilisée pour créer des objets à la place de l’appel au constructeur (opérateur new). Les sous-classes peuvent redéfinir cette méthode pour modifier la classe des objets qui seront créés.

Modèle UML

Alt text

Implémentation

Un exemple d'implémentation, une fabrique de véhicule (voiture, vélo, etc.)

Prennons des classes de véhicules héritant d'une classe mère :

enum etypeVehicule{
    eVoiture,
    eVelo
};

// classe virtuelle pure :
class Vehicule {
    public :
    Vehicule(){;}
    virtual ~Vehicule(){;}
    virtual void rouler() =0;
};

// classes filles :
class Voiture : public Vehicule {
    public :
    Voiture(){;}
    inline void rouler(){ std::cout << "je polue" << std::endl;}
};
class Velo : public Vehicule {
    public :
    Velo();
    inline void rouler(){ std::cout << "je ne polue pas" << std::endl;}
};

On pourrait imaginer le système suivant :

class fabriqueSimple {
    public :
    fabriqueSimple(){;}
    Vehicule* creerVehicule(etypeVehicule type);
};

Vehicule* fabriqueSimple::creerVehicule(etypeVehicule type)
{
    if (type == eVoiture) return new Voiture;
    if (type == eVelo) return new Velo;
    return NULL;
}

Le problème de cet exemple :

  • On veut éviter le switch/case (série de if dans notre cas) qui peut être dangereuse (ça sent la copier-couiller…)
  • On veut éviter de modifier cette classe à chaque nouvel objet.

Afin d’éviter la répétition de code, on va instancier :

  • une map permettant d’enregistrer les objets à créer
  • une fonstion Register() permettant de remplir la map

La factory de véhicule :

/// fabrique :
class fabrique {
    
    public :
    
    // constructeur :
    fabrique();
    
    // enregistrement des objets :
    static std::map<etypeVehicule,Vehicule*> m_map;
    
    // ajout de nouveau constructeur :
    void Register(etypeVehicule type,Vehicule* vehicule);
    
    // creation des objets :
    std::unique_ptr<Vehicule> creerVehicule(const etypeVehicule type);
};

Le code cpp :

//constructeur :
fabrique::fabrique()
{
}

//instantation de la map d'enregistrement des objets :
std::map<etypeVehicule,Vehicule*> fabrique::m_map = std::map<etypeVehicule,Vehicule*>();

//fonction register :
void fabrique::Register(etypeVehicule type,Vehicule* vehicule)
{
    //si la clé n'est pas déjà présente
    if(m_map.find(type)==m_map.end())
    {
        //on ajoute l'objet dans la map
        m_map[type]=vehicule;
    }
}

//creation des objets :
std::unique_ptr<Vehicule> fabrique::creerVehicule(const etypeVehicule type)
{
    //declaration de l'objet NULL a renvoyé
    std::unique_ptr<Vehicule> tmp;
    
    //on retrouve l'objet a creer dans la map
    std::map<etypeVehicule, Vehicule*>::const_iterator it=m_map.find(type);
    
    //si l'itérateur ne vaut pas map.end(), cela signifie que que la clé à été trouvée
    if(it!=m_map.end())
    {
        tmp.reset((*it).second);
    }
    
    //on pourrait lancer une exeption si la clé n'a pas été trouvée
    
    return tmp;
}

Dans le main :

fabrique fab;
fab.Register(etypeVehicule::eVelo, new Velo);
fab.Register(etypeVehicule::eVoiture, new Voiture);

std::unique_ptr<Vehicule> velo = fab.creerVehicule(etypeVehicule::eVelo);
velo->rouler();

L'implémentation

Désormais, on peut créer tous les objets que l’on souhaite sans avoir besoin de modifier la classe « fabrique ».

Pour aller plus loin :

  • Une fois que l’on récupère l’objet Vehicule, on ne connaît pas sa nature. On peut le caster en utilisant des fonctions du type isVelo(),isVoiture().
  • On voudrait qu’il existe une seule fabrique pour le programme : un singleton

Exercices

  • transformer la fabrique ci-dessus en singleton

  • créer une fabrique générique pour tous type d’objet ayant un constructeur prenant les même paramètres

La correction

Pour aller encore plus loin : la fabrique abstraite ?