views:

134

answers:

5

As described in the motivation of using the Abstract Factory, i need an interface which i want to be highly flexible, i.e, it should have a number of possible behaviors. So, following the AF design pattern, I define an abstract class with the interface functions as follows:

class WidgetFactory{
...
public:
       CreateScrollBar();
       CreateButton();
...
};

and then i define a concrete subclass of WidgetFactory for each behavior, with each subclass implementing the interface for a particular behavior.

My problem is I have my interface quite large, i.e., i have 10 functions in the abstract class and each function has 4 possible implementations. So it turns out that i have to implement 4^10 subclasses accounting for each possible behavior. Any idea or suggestion how could i avoid such an exponential blow up?

A: 

Usually we don't expect to have every possible combination of functionality.

For example we would not be mixing together the Windows CreateScrollBar and the Linux CreateButton.

So, do your 4 different implementations for each method naturally group in such a way? So you'd have a WindowsWidgetFactory and a LinuxWidgetFactory - does that idea work for you?

If not then I suspect that there's something else going on here. For really fine-grained behaviour control some kind of data-driven approach might be needed. Could you tell us a bit more about the different flavours you need to build.

djna
In my case, every possible combination is important.What do you mean by data-driven approach?
rayimag
If the varients only differed in minor behaviours (eg. colour ranges, or font sizes) rather than fundamental algorithmic differences, then the factory might be driven from a "recipe" or configuration file of some kind. Is there some kind of commonality of that sort. Otherwise I think the template approach from Martin York might be a good answer.
djna
A: 

Would using something like a command pattern inside of the abstract factory be an option. You pass the factory the commands that it should execute. That makes 1 command per implementation, one interface and 1 factory that can do all 4+ commands.

More information on the setup may help a bit more.

Bob Breznak
+1  A: 

If each of those 10 functions can have 4 implementations, and they are independent of each other (which you strongly imply by saying that you need to do all combinations), then they shouldn't be in a single factory. Make a separate interface for each, and implement it separately as well.

Pavel Minaev
You mean i have 10 different abstract factories each having one interface function?
rayimag
Yes, Of course, at this point, you might not even need an interface class - for a single function, `std::tr1::function` (or `boost::function` if your C++ implementation does not support TR1 yet) will do.
Pavel Minaev
+2  A: 

Have a seprate factory for each of the independt interfaces then have a master factory where you can register all the minor factories.

class ScrollBarFactory
{
    public:
        CreateScrollBar();
};
class ButtonFactory
{
    public:
        CreateButton();
};


// I just used templates as a quick example
// This can be doen in many ways. I hope you get the idea.
template<typename SF,typename BF>
class WidgetFactory
{
    public:
        CreateScrollBar()   {scrollbarFactory.CreateScrollBar();}
        CreateButton()      {buttonFactory.CreateButton();}
    private:
        SF    scrollbarFactory;
        BF    buttonFactory;
};
Martin York
A: 

Actually this problem is discussed in GoF book. The solution is to use Bridge pattern. But I`m not sure if you have the same problem as it seems strange to me that

i have 10 functions in the abstract class and each function has 4 possible implementations. So it turns out that i have to implement 4^10 subclasses accounting for each possible behavior.

Can`t get it, how do you get so much? If you need to make a really flexible interface and need to make some additions to windows like implement a scrollbar, add a border add specil border and spawning your classes for that, then the better solution is to use decorator pattern. This will make it easy to combine scrollbars, borders and anything together.

Yaroslav Yakovlev