Design problem: Factory pattern needs 'static virtual'?

Discussion in 'C++' started by Markus Dehmann, Jan 3, 2008.

  1. I need a simple object serialization, where loading an object from
    file looks like this:

    Foo* foo1 = FooFactory::create("./saved/foo1.a321f23d");
    Foo* foo2 = FooFactory::create("./saved/foo2.eb287ac8");

    Now, Foo is an abstract base class, and FooFactory contains a static
    function which again calls static create functions on Foo1 or Foo2
    (see code for all classes below). The problem is that all these
    functions are static, but I also want them to be part of the (virtual)
    Foo interface. But virtual static functions are not allowed.

    You might say that Foo1::create(...) should not be a member function,
    but just a global function outside of Foo1. But I want classes derived
    from Foo1 to be able to inherit or override create(...).

    How should I design this properly?

    Thanks! Markus

    <code>

    class Foo {
    public:
    // virtual static std::string type() const = 0; // not
    allowed
    // virtual static Foo* create(const std::string& dataLocation) =
    0; // not allowed
    // other functions that constiute the Foo
    interface
    };

    class Foo1 : public Foo {
    public:
    static std::string type() {
    static const std::string t = "Foo1";
    return t;
    }
    static Foo* create(const std::string& dataLocation) {
    return new Foo1(/* parameters according to data read from
    dataLocation*/);
    }
    };
    class Foo2 : public Foo1 {
    public:
    static std::string type() {
    static const std::string t = "Foo2";
    return t;
    }
    // function "create" is derived from
    Foo1
    };

    namespace FooFactory {
    Foo* create(const std::string& dataLocation) {
    const std::string type =
    getType(dataLocation);
    if(type == Foo1::type()){
    return Foo1::create(dataLocation);
    }
    else if(type == Foo2::type()){
    return Foo2::create(dataLocation);
    }
    }
    } // end namespace

    </code>
     
    Markus Dehmann, Jan 3, 2008
    #1
    1. Advertising

  2. Markus Dehmann

    kwikius Guest

    On Jan 3, 11:49 pm, Markus Dehmann <> wrote:
    > I need a simple object serialization, where loading an object from
    > file looks like this:
    >
    >   Foo* foo1 = FooFactory::create("./saved/foo1.a321f23d");
    >   Foo* foo2 = FooFactory::create("./saved/foo2.eb287ac8");
    >
    > Now, Foo is an abstract base class, and FooFactory contains a static
    > function which again calls static create functions on Foo1 or Foo2
    > (see code for all classes below). The problem is that all these
    > functions are static, but I also want them to be part of the (virtual)
    > Foo interface. But virtual static functions are not allowed.
    >
    > You might say that Foo1::create(...) should not be a member function,
    > but just a global function outside of Foo1. But I want classes derived
    > from Foo1 to be able to inherit or override create(...).



    > How should I design this properly?


    > namespace FooFactory {
    >   Foo* create(const std::string& dataLocation) {
    >     const std::string type =
    > getType(dataLocation);
    >     if(type == Foo1::type()){
    >       return Foo1::create(dataLocation);
    >     }
    >     else if(type == Foo2::type()){
    >       return Foo2::create(dataLocation);
    >     }
    >   }


    look up "static polymorphism" or named conformance to an interface

    Simply put , use a static create function and if a derived wishes to
    override it adds its own static create function, which hides that in
    the base class otherwise the compiler will find the base class
    version, In fact there is no need for derivation, as any class with a
    static create function , or whose base has a static create function
    can be used, assuming the return type is viable.

    regards
    Andy Little
     
    kwikius, Jan 4, 2008
    #2
    1. Advertising

  3. Markus Dehmann

    James Kanze Guest

    On Jan 4, 12:49 am, Markus Dehmann <> wrote:
    > I need a simple object serialization, where loading an object from
    > file looks like this:


    > Foo* foo1 = FooFactory::create("./saved/foo1.a321f23d");
    > Foo* foo2 = FooFactory::create("./saved/foo2.eb287ac8");


    > Now, Foo is an abstract base class, and FooFactory contains a
    > static function which again calls static create functions on
    > Foo1 or Foo2 (see code for all classes below). The problem is
    > that all these functions are static, but I also want them to
    > be part of the (virtual) Foo interface. But virtual static
    > functions are not allowed.


    > You might say that Foo1::create(...) should not be a member
    > function, but just a global function outside of Foo1. But I
    > want classes derived from Foo1 to be able to inherit or
    > override create(...).


    I'm not sure I understand what you're asking for. You have
    different derived classes of Foo, each with its own function
    create. You want the compiler to somehow call the correct
    instance of create, according to the dynamic type. But the
    dynamic type of what? How do you determine which Foo??::create
    should be called?

    > How should I design this properly?


    > <code>


    > class Foo {
    > public:
    > // virtual static std::string type() const = 0; // not
    > allowed
    > // virtual static Foo* create(const std::string& dataLocation) =
    > 0; // not allowed
    > // other functions that constiute the Foo
    > interface
    > };


    > class Foo1 : public Foo {
    > public:
    > static std::string type() {
    > static const std::string t = "Foo1";
    > return t;
    > }
    > static Foo* create(const std::string& dataLocation) {
    > return new Foo1(/* parameters according to data read from
    > dataLocation*/);
    > }};


    > class Foo2 : public Foo1 {
    > public:
    > static std::string type() {
    > static const std::string t = "Foo2";
    > return t;
    > }
    > // function "create" is derived from
    > Foo1
    > };


    > namespace FooFactory {
    > Foo* create(const std::string& dataLocation) {
    > const std::string type =
    > getType(dataLocation);
    > if(type == Foo1::type()){
    > return Foo1::create(dataLocation);
    > }
    > else if(type == Foo2::type()){
    > return Foo2::create(dataLocation);
    > }
    > }
    > } // end namespace
    > </code>


    Wouldn't some sort of table be more appropriate? Say an
    std::map< std::string, Foo* (*)( std::string ) >. With:

    typedef std::map< std::string, Foo* (*)( std::string ) >
    FooFactoryMap ;
    FooFactoryMap ourMap ;

    Foo*
    create(
    std::string const& dataLocation )
    {
    FooFactoryMap::const_iterator
    entry
    = ourMap.find( getType( dataLocation ) ) ;
    return entry == ourMap.end()
    ? NULL
    : (*entry->second)() ;
    }

    You'll have to arrange to initialize the map somehow, but that
    shouldn't be any more of a bother than maintaining all of your
    if's.

    James Kanze (GABI Software) mailto:
    Conseils en informatique orient�e objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jan 4, 2008
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Medi Montaseri
    Replies:
    17
    Views:
    895
    Medi Montaseri
    Sep 3, 2003
  2. sunny
    Replies:
    1
    Views:
    470
    Salt_Peter
    Dec 7, 2006
  3. C#
    Replies:
    4
    Views:
    420
  4. Pallav singh
    Replies:
    0
    Views:
    373
    Pallav singh
    Jan 22, 2012
  5. Pallav singh
    Replies:
    0
    Views:
    410
    Pallav singh
    Jan 22, 2012
Loading...

Share This Page