Virtual constructor idiom and factory design

∥☆過路亽.° 提交于 2019-12-07 17:29:46

问题


In virtual constructor idiom there are virtual functions which returns new object OR copy of the object using virtual functions. But then to call these virtual functions polymorphic way, you must have object of that class created using actual constructor.

In design pattern context, it means client is aware of the type of object before using polymorphic way of object creation?


回答1:


The client doesn't necessarily have to be aware of the concrete type. For example, consider this hierarchy:

struct Base
{
    virtual ~Base();
    virtual Base * clone() const = 0;
    static Base * create(std::string const &);
    // ...
};

struct A : Base { A * clone() const { return new A(*this); } /* ... */ };
struct B : Base { B * clone() const { return new B(*this); } /* ... */ };
struct C : Base { C * clone() const { return new C(*this); } /* ... */ };

Base * Base::create(std::string const & id)
{
    if (id == "MakeA") return new A;
    else return new C;
};

In this case, the client can make and copy an existing object like so:

Base * p = Base::create("IWantB");  // or std::unique_ptr<Base> !
Base * q = p->clone();

In neither case does the client ever know the dynamic type of *p or *q.




回答2:


class Base
{
public:
    Base() { }

    virtual ~Base() { }

    // The "Virtual Constructor"
    static Base *Create(int id);

    // The "Virtual Copy Constructor"
    virtual Base *Clone() = 0;
};

Base *Base::Create(int id)
{

    if( id == 1 )
    {
        return new Derived1;
    }
}

class Derived1 : public Base
{
public:
    Derived1()
    {
        cout << "Derived1 created" << endl;
    }

    Derived1(const Derived1& rhs)
    {
        cout << "Derived1 created by deep copy" << endl;
    }

    ~Derived1()
    {
        cout << "~Derived1 destroyed" << endl;
    }

    Base *Clone()
    {
        return new Derived1(*this);
    }
};

Now in Main when you do

void main()
{
        cout << "Enter ID (1, 2 or 3): ";
        cin >> input;
        Base *pBase = Base::Create(input);
        Base *pCopy = CreateCopy(pBase);

        //Dont know what object is created but still access functions thru base pointer
}

Base *CreateCopy(Base *pBase)
{
  return pBase->Clone();
}

the client need not know the type of class it inherits but still call some function.




回答3:


Eventually something somewhere has to know the concrete type of your objects. The idea of hiding that detail leads to a pattern called inversion of control or, more lately, dependency injection.

The thought is to nominate one component in the whole program which is aware of the concrete types used. It then becomes the responsibility of this component to assemble your object graph; other components take their dependencies as interfaces only, which are passed in on construction or through methods.

There are a handful of dependency injector implementations for C++: spring-cpp, autumnframework and dicpp come to mind. I've authored one myself, called sauce, which emulates the style of a java framework named guice.




回答4:


The virtual constructor idiom the client is not aware of the derived type. The whole purpose of this idiom is to enable cloning of an object through the base pointer. Here is an example:

class base
{
public:
   base* clone()
   {
       // NVI: implemented by derived classes.
       do_clone();
   }

 protected:
   virtual base* do_clone = 0;
};

class derived : public base
{
protected:
    virtual derived* do_clone()
    {
        // Implementation. Note the return value is not base*.
    }
 };

See this ACCU article for details: http://accu.org/index.php/journals/522



来源:https://stackoverflow.com/questions/11574075/virtual-constructor-idiom-and-factory-design

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!