Wzorce projektowe (5)

Autor: Damian Chodorek • Opublikowany: 20 lipca 2015 • Ostatnia aktualizacja: 21 lipca 2015 • Kategoria: kursy, wzorce projektowe

Uogólniona fabryka obiektów.

W poprzedniej części, poznałeś wzorzec fabryki obiektów. W tej części dowiesz się jak wygląda uogólnienie tego wzorca przy pomocy szablonów klas.

Uogólnieniem powinien być szablon, który umożliwia wybranie:

  • AbstractProduct – tzn abstrakcyjną klasę, po której dziedziczą wszystkie konkretne produkty,
  • IdentifierType – obiekt, który będzie pełnił rolę ID, na podstawie którego będą tworzone konkretne produkty,
  • ProductCreator – funkcja albo funktor specjalizowany do tworzenia obiektów jednego i tylko jednego typu,
  • FactoryErrorPolicy – wytyczna pozwalająca na dostosowanie obsługi błędów do wyróżnionych scenariuszy.

Szablon

template <class AbstractProduct,
typename IdentifierType,
ProductCreator = AbstractProduct*(*)(),
template <typename, class> class FactoryErrorPolicy>
class Factory: public FactoryErrorPolicy<IdentifierType, AbstractProduct>{

public:
    bool Register(const IdentifierType& id, ProductCreator creator){
        return associations.insert(AssocMap::value_type(id, creator)).second;
    }

    bool Unregister(const IdentifierType& id){
        return associations.erase(id)==1;
    }

    AbstractProduct* CreateObject(const IdentifierType& id){
        typename AssocMap::const_iterator i=associations.find(id);
        if(i!=associations.end()){
            return (i->second)();
        }

        return OnUnknownType(id);
    }

private:
    typedef std::map<IdentifierType, ProductCreator> AssocMap;
    AssocMap associations;
};

// Klasa błędu
template< class IdentifierType, class ProductType>
class DefaultFactoryError
{
public:
    class Exception: public std::exception
    {
    public:
        Exception(const IdentifierType& uid): unknownId(uid){}
 
        virtual const char* what(){
            return "nieznany typ obiektu";
        } 

        const IdentifierType& GetId(){
            return unknownId;
        }

    private:
        IdentifierType unknownId;
    };

protected:
    static ProductType* OnUnknownType(const IdentifierType& Id){
        throw Exception(id);
    }
};

część 6

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.