Abstract factory pattern

From wiki.visual-prolog.com

From wikipedia::Abstract factory pattern:

A software design pattern, the Abstract Factory Pattern provides a way to encapsulate a group of individual factories that have a common theme. In normal usage, the client software would create a concrete implementation of the abstract factory and then use the generic interfaces to create the concrete objects that are part of the theme. The client does not know (nor care) about which concrete objects it gets from each of these internal factories since it uses only the generic interfaces of their products. This pattern separates the details of implementation of a set of objects from its general usage.

Example

A program must work with one of two different GUI systems: win or osx. Each of the GUI systems provides buttons and edit controls. The controls are represented by the same interfaces in the two GUI systems, but different classes:

interface win class osx class
button winButton : button osxButton : button
edit winEdit : edit osxEdit : edit

So when we use the win system, we must use the win- classes; and when we use the osx system, we must use the osx- classes. Rather than testing for GUI system each time we want to create a button or edit control, we use an abstract factory.

The abstract factory is an object that can create (i.e. manufacture) buttons and edit controls:

interface guiFactory
    predicates
        createButton : () -> button NewButton.
        createEdit : () -> edit Edit.
end interface guiFactory

We implement two factories, one for win- controls:

class winFactory : guiFactory
end class winFactory
implement winFactory
    clauses
        createButton() = winButton::new().
    clauses
        createEdit() = winEdit::new().
end implement winFactory

and one for osx- controls:

class osxFactory : guiFactory
end class osxFactory
implement osxFactory
    clauses
        createButton() = osxButton::new().
    clauses
        createEdit() = osxEdit::new().
end implement osxFactory

Now we can some where create either a win-factory or an osx-factory, and in the rest of the program we will create controls using this factory.

The goal here is just for illustrative purposes; in a real program the GUI system would have to be initialized, and the button must be drawn somewhere.

goal
    if 1 = config::getAttribute("OS_TYPE") then
        GuiFactory = winFactory::new()
    else
        GuiFactory = osxFactory::new()
    end if,
    Button = GuiFactory:createButton(),
    Button:setText("Play"),
    Button:paint().


Additional Notes

  1. In the example above we create one factory at the very start of the program and retain it throughout the entire execution. But in other setup's you may create several factories for each their purpose, or create factories that are only temporarily and then disposed again. Consider for example a print version of the factory above. You might create an instance of this factory, when you want to print a "dialog" and then dispose it again once you have printed the dialog. So this factory will only live temporarily and it may coexist with one of the other factories.
  2. The client software does not have any knowledge about the concrete factories. Particularly, it does not know how many there are, the name, purpose or any other characteristics about them.

References