Search code examples
oopfactory-pattern

Factory Pattern - Is having multiple factories a good idea?


I am designing a system that lets a user assign a specific task to be performed when a button is pressed. The task to be performed can be assigned to all sorts of things. So I have an abstract base class called "ButtonTask", and all other tasks inherit from this base to implement the task to be performed along with the associated data it needs to know. This way I can use polymorphism to abstract away all the specifics, I just call "PerformTask" without having to care about what type it actually is. So far so good.

The actual task itself can be set in may different ways, the user may change the task with a UI menu, the task may be read from a file, and also the task may be set remotely via a network message.

At the moment I have a factory function that will create the correct derived type based on the network message, and return a pointer to the base type. The problem is that the UI menu and the file reading feel like they need their own factory method for object creation, as they are inherently different from one another. Is it generally a good idea to have multiple factories for this kind of problem? I can't really think of another way around this problem but perhaps there's something neater I can do.


Solution

  • The only good reason I see to implement multiple factory methods is if you want to be able to create the objects with different sets of initial attributes, for instance by allowing the caller to specify some attributes and setting default values for others - the equivalent of having multiple public constructors.

    If the idea is that the tasks are independent of the way they were initiated (GUI, network, etc), then I don't see a need for separate factory methods. Instead, I would say that one of the duties of the factory is to achieve this very abstraction. In other words, calling the same factory from three different parts of the code is absolutely fine. It is probably a good idea to make the factory method static or to make the factory a singleton object, though.

    If on the other hand you have a situation where certain tasks can only ever be initiated from the network and others from the GUI, and only a few can be initiated in all three ways, then it might be worthwhile to rethink the design a bit. You should then consider adding another level of abstract Task classes, eg CommonTask, GuiTask, NetworkTask, FileTask, and have factories for them instead of ButtonTask. This is obviously more complex and whether or not it's worth it depends on the number of task classes and the structure of your code.

    What you want to avoid is a situation where users of the factory are aware of which specific subclasses of ButtonTask they can receive from the factory. That's a "false base class" situation, ie one where the base class is not a true abstraction of the whole set of its subclasses, and you get out of it by adding the extra subclass layer as outlined above.

    Other than that, you might also want to consider renaming ButtonTask; it sounds like a GUI-only task just from the name.