Abstract Factory is a design pattern for software development . Provides an interface to create families of related or dependent objects between them without specifying a specific class.
Summary
[ hide ]
- 1 Context and problem
- 2 Static appearance
- 3 Typical structure
- 4 An example
- 5 See also
- 6 External links
- 7 Sources
Context and problem
Context: We must create different objects, all belonging to the same family. For example: the libraries to create graphical interfaces usually use this pattern and each family would be a different operating system. So, the user declares a Button, but more internally what he is creating is a Windows Button or a Linux Button, for example.
The problem this pattern is trying to solve is creating different families of objects.
The Abstract Factory pattern is recommended when the inclusion of new product families is foreseen, but it can be counterproductive when new products are added or existing ones are changed, since it would affect all the families created.
Static appearance
Typical structure
- Customer: The class that will call the appropriate factory since it needs to create one of the objects that the factory provides, that is, Customer wants to obtain an instance of one of the products (ProductA, ProductB).
- AbstractFactory: It is a definition of the factory interfaces. You must provide a method for obtaining each object you can create. (“createProductA ()” and “createProductB ()”)
- Concrete factories: These are the different families of products. It provides the specific instance of which it is in charge of creating. In this way we can have a factory that creates the graphic elements for Windows and another that creates them for Linux , being able to easily put (creating a new one) another one that creates them for MacOS , for example.
- Abstract product: Definition of the interfaces for the generic product family . In the diagram they are “ProductA” and “ProductB”. In an example of graphic interfaces, it could be all the elements: Button , Window , Text Box , Combo … The client will work directly on this interface, which will be implemented by the different specific products.
- Concrete product: Implementation of the different products. It could be for example “ButtonWindows” and “ButtonLinux”. As both implement “Button” the client will not know if it is on Windows or Linux, since it will work directly on the superclass or interface.
An example
To show the concept of the Abstract Factory we are going to make a simple clock that shows us the current time. As we know, the time can be displayed in 24Hrs format or it can be displayed in AM / PM format. Remembering that it is by way of example, we are going to use the Date class in a way that it should not, and probably the clock would do it in a simpler way, but for our example its use is perfect. As in the case of the dictionary, we will make an abstract Clock class and two implementations for each of the formats, and a class that contains the Factory Method method. The thing would look something like this:
The Clock class:
public abstract class Clock {
abstract String dameLaHora ();
}
The class that is given the time in AM / PM format:
public class ClockAmPm extends Clock {
public ClockAmPm () {
}
public String dameLaHora () {
Date d = new Date ();
int hour = d . getHours ();
int minutes = d . getMinutes ();
int seconds = d . getSeconds ();
String tr ;
if ( time & lt ; = 12 ) {
tr = “Are” + Time + “:” + min +”:” + seconds + “AM” ;
} else {
tr = “They are the” + ( hour – 12 ) + “:” + minutes + “:” + seconds + “PM” ;
}
return tr ;
}
}
The one that gives us the time in 24-hour format:
public class Clock24Hrs extends Clock {
public String dameLaHora () {
Date d = new Date ();
int hour = d . getHours ();
int minutes = d . getMinutes ();
int seconds = d . getSeconds ();
String tr ;
tr = “It is the” + hour + “:” + minutes + “:” + seconds + “” ;
return tr ;
}
}
Our class that contains the method that the instances choose. Unlike the previous post, the parameter that the method receives is now an integer, which accepts the integers specified as static constants in the class. This is used a lot to avoid guessing the parameters that the method accepts:
public class ClockFactory {
public static final int CLOCK_AM_PM = 0 ;
public static final int CLOCK_24_HRS = 1 ;
public ClockFactory () {
}
public static Clock createReloj ( int tipoDeReloj ) {
if ( tipoDeReloj == RelojFactory . RELOJ_24_HRS ) {
return new Reloj24Hrs ();
}
if ( clockType == ClockFactory . CLOCK_AM_PM ) {
return new ClockAmPm ();
}
return null ;
}
}
And finally the client class, which will be the end user:
public class MainClient {
public static void main ( String [] args ) {
Clock r = ClockFactory . createReloj ( RelojFactory . CLOCK_24_HRS );
System . out . println ( r . dameLaHora ());
}
}
Up to here we have two factories: one of words, and the one that we have just made that gives us the time.