Search code examples
c++oopfactory-pattern

Should a factory take care of reconstructing serialized objects?


I'm working on a homework in which I have to implement the Abstract Factory Pattern. I am given a template of the factory class which I need to implement (and adapt) in order to make a test program pass.

The template looks like this:

typedef Shape *(createShapeFunction)(void);
/* thrown when a shape cannot be read from a stream */

class WrongFormatException { };

class ShapeFactory
{
    public:
        static void registerFunction(const std::string &, const createShapeFunction *);
        static Shape *createShape(const std::string &);
        static Shape *createShape(std::istream &);

    private:
        std::map<std::string, createShapeFunction *> creationFunctions;

        ShapeFactory();
        static ShapeFactory *getShapeFactory();
};

The first overload of the createShape method is straight forward however the 2nd overload is used in a scenario which demands the factory o know how its products are serialized.

To be more precise: a bunch of shapes with random parameters are generated, serialized to a stream and then the stream is fed to the 2nd overload in order to reconstruct the objects one by one.

This does not seem right according to what I have learned about OOP because deserializing the objects in this manner would imply knowledge on how they are serialized, which inevitably leads to violation of the encapsulation principle (by leaking implementation details about the products to the factory).

Is this right or perhaps I'm missing something?


Solution

  • I think your factory class is fine, and not violating any of the SOLID principles of OO design.

    The factory should know what the classes it creates have in common. In other words: it knows the base class invariants, including the stream token that represents a valid object. Throwing an exception in case of bad input is entirely valid. Since that knowledge is stored in the registry, the class itself does not depend on concrete classes, but only on the abstract base class (the Dependency Inversion Principle).

    What it does not know at compile-time is the entire class hierarchy. That knowledge is only apparent at runtime through its registry. This effectively changes a static type switch into a dynamc map lookup, which is the preferred use of polymorphism in OO and makes it easy to construct new subclasses without having to modify the factory class (the so-called Open/Closed Principle).