Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Virtual constructor idiom and factory design

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?

like image 707
Sach Avatar asked Jan 16 '23 01:01

Sach


2 Answers

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.

like image 148
Kerrek SB Avatar answered Jan 18 '23 14:01

Kerrek SB


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.

like image 23
Jeeva Avatar answered Jan 18 '23 15:01

Jeeva