What is a factory and why would I want to use one?
The Factory design pattern is ideal in circumstances when you need to create multiple instances of an object at run time. Rather than explicitly creating each instance you can initialize many instances. Additionally, you can encapsulate complex creation code that can be reused multiple times.
Example:
public class Person {
int ID;
String gender;
public Person(int ID,String gender){
this.ID=ID;
this.gender=gender;
}
public int getID() {
return ID;
}
public String getGender() {
return gender;
}
}
public class PersonFactory{
public static Person createMale(int id){
return new Person(id,"M");
}
public static Person createFemale(int id){
return new Person(id,"F");
}
}
public class factorytest{
public static void main(String[]args){
Person[] pList= new Person[100];
for(int x=0;x<100;x++){
pList[x]=PersonFactory.createMale(x);
}
}
}
In this example we encapsulate the details of the gender initialization parameter and can simply ask the PersonFactory to createMale or createFemale Person objects.
Factory is an object for creating other objects.
It creates objects without exposing the instantiation logic to the client.
Use this pattern when you don't want to expose object instantiation logic to the client/caller
Related posts:
Design Patterns: Factory vs Factory method vs Abstract Factory
What is the basic difference between the Factory and Abstract Factory Patterns?
What is a factory ?
Wikipedia explains in detail
Also see answer from legendary BalusC over here about many GoF patterns examples
In simple words Factory creates\initialize\allocate the objects that you can use in the code.
e.g if you have a person abstract class or interface or even a concrete class and you declare it in an other class e.g. private person;
that is just that object has been declared but not created. You will either use new or some dependency injection or a factory to create this object (there are other options as well e.g Locator etc).
Why would I want to use one?
Now you might need to a have specific type of person e.g teacher or even person might have different implantation based of different configurations etc .Factory pattern takes care of this.It allows you or should I say frees you from worrying about what implementation or initialization of particular class should be used.
In simple terms, Factory is an OO design pattern that deals with creating objects without specifying the exact class of object that is to be created.
A good reason to use it is well defined in wikipedia:
The creation of an object often requires complex processes not appropriate to include within a composing object. The object's creation may lead to a significant duplication of code, may require information not accessible to the composing object, may not provide a sufficient level of abstraction, or may otherwise not be part of the composing object's concerns. The factory method design pattern handles these problems by defining a separate method for creating the objects, which subclasses can then override to specify the derived type of product that will be created.
The factory is an object, that creates objects. The common usage includes two cases:
Integer.valueOf()
, which is a so-called factory method) or choose a concrete implementation depending on some conditions - e.g. supplied argument or pre-defined options (see XPathFactory
class in Java API for XML Processing)SomeFactory<T>
in a generic method).Are you familiar with JDBC? It's one and all (abstract) factory. It's a good real world example.
// Factory method. Loads the driver by given classname. It actually returns a
// concrete Class<Driver>. However, we don't need it here, so we just ignore it.
// It can be any driver class name. The MySQL one here is just an example.
// Under the covers, it will do DriverManager.registerDriver(new Driver()).
Class.forName("com.mysql.jdbc.Driver");
// Abstract factory. This lets the driver return a concrete connection for the
// given URL. You can just declare it against java.sql.Connection interface.
// Under the covers, the DriverManager will find the MySQL driver by URL and call
// driver.connect() which in turn will return new ConnectionImpl().
Connection connection = DriverManager.getConnection(url);
// Abstract factory. This lets the driver return a concrete statement from the
// connection. You can just declare it against java.sql.Statement interface.
// Under the covers, the MySQL ConnectionImpl will return new StatementImpl().
Statement statement = connection.createStatement();
// Abstract factory. This lets the driver return a concrete result set from the
// statement. You can just declare it against java.sql.ResultSet interface.
// Under the covers, the MySQL StatementImpl will return new ResultSetImpl().
ResultSet resultSet = statement.executeQuery(sql);
You do not need to have a single line of JDBC driver specific import
in your code. You do not need to do import com.mysql.jdbc.ConnectionImpl
or something. You just have to declare everything against java.sql.*
. You do not need to do connection = new ConnectionImpl();
yourself. You just have to get it from an abstract factory as part of a standard API.
If you make the JDBC driver class name a variable which can be configured externally (e.g. properties file) and write ANSI compatible SQL queries, then you do not ever need to rewrite, recompile, rebuild and redistribute your Java application for every single database vendor and/or JDBC driver which the world is aware of. You just have to drop the desired JDBC driver JAR file in the runtime classpath and provide configuration by some (properties) file without the need to change any line of Java code whenever you want to switch of DB or reuse the app on a different DB.
That's the power of interfaces and abstract factories.
Another known real world example is Java EE. Substitute "JDBC" with "Java EE" and "JDBC driver" with "Java EE application server" (WildFly, TomEE, GlassFish, Liberty, etc).