views:

66

answers:

1

So here's the deal:

I have a concrete class Window, representing an operating system window which will be be used for drawing. Window can take on many types, such as fullscreen, fixed window, resizable window, borderless window etc. This is implemented using an interface IWindowType, in which the specific types derive from (classes are stripped down to focus on the point).

class IWindowType
{
public:
    virtual void createWindow(unsigned short width, unsigned short height) = 0;
};

class FixedWindow: public IWindowType
{
public:
    virtual void createWindow(unsigned short width, unsigned short height) 
    { 
         // Fixed window creation implementation
    }
};

Any further implementations can be derived, or the underlying window creation method can be changed easily. Window needs to store it's type so it can re-call createWindow() if it needs to, for an explicit window resize or a complete type change (e.g. fixed to fullscreen). Therefore, it stores an IWindowType pointer.

class Window
{
public:

private:
    IWindowType* mType;
};

My problem is being able to store the type inside Window, giving window the responsibility for managing it's type. I have two solutions with this design, neither of which I really like the look of.

First is to have the client pass a dynamically allocated window type and have window deal with memeory de-allocation.

Window testWindow;
testWindow.setType(new FixedWindow());

This does work, but it requires remembering to pass a dynamically allocated object, as well as an ugly use of new with no matching delete (as far as the client is concerned, anyway).

The second I found after research was the use of a virtual clone() method, which also works and has much better syntax, since it performs a deep copy of whatever derived class is passed in, and window takes control of this copied object.

IWindowType* FixedWindow::clone() const
{
    return new FixedWindow(*this);
} 

void Window::setType(const IWindowType& type)
{
    if(mType)
        delete mType;

    mType = type.clone()
}

Window testWindow;
testWindow.setType(FixedWindow());

However, I feel creating a clone() method for each class that requires this functionality (I can see a lot of classes requiring it with this kind of design) can become not only tedious, but clone() may be used out of this context, which I don't really want.

So my question: Are there any other ways to pass ownership of the derived type passed to setType() to Window i.e. giving Window it's own copy to manage? I don't require to keep this design, I am simply experimenting ways of doing things, so if a better design approach is available, it is welcome.

A: 

Do you need access to those type objects outside the Window class? If you don't, I would try to hide the fact that you're using a class to represent the type. Maybe you could do something like this:

class Window
{
public:
    enum WindowType
    {
        FixedWindow,
        //more types
    };

    void setType(WindowType type)
    {
        delete mtype;

        //move type creation to some factory class
        mtype = TypeFactory::createType(type);
    }

private:
    IWindowType* mType;
};

This way, you don't have to worry about how to get the type objects from the outside world. They just have to specify what kind of type the window should be, the window decides how that type is represented.

Job