Definition
Factory Method
The Factory Method Pattern defines an interface for creating an object, but lets subclass decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.
Figure 01. Class diagram of the Factory Method. Ref:http://en.wikipedia.org/wiki/Factory_method_pattern
Singleton
The Singleton Pattern ensures a class has only one instance, and provides a global point of access to it.
Figure 02. Singleton class Ref: http://en.wikipedia.org/wiki/Singleton_pattern
Scenario
One of the applications of the Singleton Pattern is in a Factory class, due to the fact that factories don’t need to be instantiated multiple times and just one factory can create as many objects as required, we can save memory in the system making the Factory a Singleton.
For this reason we will create a small factory that will create two (or can be more) types of users:
- A simple user
- A super user
What is going to differentiate these users is going to be the rights attached to them:
- A simple user will have these rights: Review and Edit customers.
- A super user will have these rights: Remove and Create customers.
For the design of the proposed study case we will refer to the following class diagram:
Figure 03. Class diagram of the solution proposed
As it can be seen in this figure, we will have two factories that will create a specific type of user, and an abstract factory that will set all the common data for both factories that extends the abstract class UserWithRightsFactory.
UserWithRightsFactory.java
package chris.desingpatterns.factorysingleton.factory;
import java.util.ArrayList;
import java.util.List;
import chris.desingpatterns.factorysingleton.server.pojos.Right;
public abstract class UserWithRightsFactory {
protected abstract User getNewUser();
public User createUser(){
User user = getNewUser();
List<Right> rights = new ArrayList<Right>();
setBasicRights(rights);
if(user instanceof SuperUser){
setSuperRights(rights);
}
user.setRights(rights);
return user;
}
private void setBasicRights(List<Right> rights){
//Basic rights
rights.add(Right.REVIEW_CUSTOMER);
rights.add(Right.EDIT_CUSTOMER);
}
private void setSuperRights(List<Right> rights){
//Super rights
rights.add(Right.REMOVE_CUSTOMER);
rights.add(Right.CREATE_CUSTOMER);
}
}
package chris.desingpatterns.factorysingleton.factory;
public class SimpleUserRightsFactory extends UserWithRightsFactory {
private static SimpleUserRightsFactory uniqueInstance;
private SimpleUserRightsFactory() {}
public static SimpleUserRightsFactory getInstance(){
if(uniqueInstance == null){
uniqueInstance = new SimpleUserRightsFactory();
}
return uniqueInstance;
}
protected User getNewUser() {
return new User();
}
}
package chris.desingpatterns.factorysingleton;
import java.util.ArrayList;
import java.util.List;
import chris.desingpatterns.factorysingleton.factory.SimpleUserRightsFactory;
import chris.desingpatterns.factorysingleton.factory.SuperUser;
import chris.desingpatterns.factorysingleton.factory.SuperUserRightsFactory;
import chris.desingpatterns.factorysingleton.factory.User;
import chris.desingpatterns.factorysingleton.factory.UserWithRightsFactory;
import chris.desingpatterns.factorysingleton.server.pojos.Address;
import chris.desingpatterns.factorysingleton.server.pojos.ContactInformation;
import chris.desingpatterns.factorysingleton.server.pojos.Identification;
import chris.desingpatterns.factorysingleton.server.pojos.IdentificationDocument;
import chris.desingpatterns.factorysingleton.server.pojos.Name;
public class Main {
public static void main(String... args){
Name name = new Name();
name.setFirstName("Christian");
name.setLastName("Roman");
Address address = new Address();
address.setCity("La Paz");
address.setCountry("Bolivia");
address.setHouseNumber("333");
address.setStreet("Ocobaya");
Identification identifcation = new Identification();
identifcation.setDocument(IdentificationDocument.ID);
identifcation.setNumber("123456789");
ContactInformation contactInformation = new ContactInformation();
contactInformation.setEmail("cralcubo@yahoo.com");
contactInformation.setTelephone("0652630333");
User simpleUser = createSimpleUser(name, address,
identifcation, contactInformation);
Name nameB = new Name();
nameB.setFirstName("Karl");
nameB.setLastName("Taylor");
Address addressB = new Address();
addressB.setCity("Utrecht");
addressB.setCountry("Netherlands");
addressB.setHouseNumber("2");
addressB.setStreet("Zijdebalenstraat");
Identification identificationB = new Identification();
identificationB.setDocument(IdentificationDocument.DRIVING_LICENSE);
identificationB.setNumber("ABCD1234564");
ContactInformation contactInformationB = new ContactInformation();
contactInformationB.setEmail("karl@taylor.com");
contactInformationB.setTelephone("0612345678");
User simpleUserB = createSimpleUser(nameB, addressB,
identificationB, contactInformationB);
Name nameC = new Name();
nameC.setFirstName("Anna");
nameC.setLastName("Korte");
Address addressC = new Address();
addressC.setCity("Groningen");
addressC.setCountry("Netherlands");
addressC.setHouseNumber("568");
addressC.setStreet("Boliviastraat");
Identification identificationC = new Identification();
identificationC.setDocument(IdentificationDocument.PASSPORT);
identificationC.setNumber("9875631XX");
ContactInformation contactInformationC = new ContactInformation();
contactInformationC.setEmail("anna@gmail.com");
contactInformationC.setTelephone("0652369875");
User superUser = createSuperUser(nameC, addressC,
identificationC, contactInformationC);
List<User> usersManged = new ArrayList<User>();
usersManged.add(simpleUser);
usersManged.add(simpleUserB);
((SuperUser)superUser).setUsersManged(usersManged );
//Optionally you could print the info of all the users
//created by the factories.
//printAllUsersinformation(simpleUser, simpleUserB, superUser);
}
/**
* Method that will print all the information of the
* users created in the Main method.
*
* @param users
*/
private static void printAllUsersinformation(User ...users) {
for(User user : users){
String userType = (user instanceof SuperUser) ? "SUPER USER" : "USER";
System.out.println(".:. " + userType + " .:.");
System.out.println(user.toString());
if(user instanceof SuperUser){
System.out.println("Users Managed: ");
for(User simpleUser : ((SuperUser)user).getUsersManged()){
System.out.println("- " + simpleUser.getName().getFirstName());
}
}
}
}
/**
* Method that will create a Simple User.
*
* @param name
* @param address
* @param identification
* @param contactInformation
* @return
*/
private static User createSimpleUser(Name name,
Address address,
Identification identification,
ContactInformation contactInformation){
UserWithRightsFactory simpleUserRightsFactory =
SimpleUserRightsFactory.getInstance();
return createUser(simpleUserRightsFactory, name, address,
identification, contactInformation);
}
/**
* Method that will create a Super User.
*
* @param name
* @param address
* @param identification
* @param contactInformation
* @return
*/
private static User createSuperUser(Name name,
Address address,
Identification identification,
ContactInformation contactInformation){
UserWithRightsFactory superUserRightsFactory =
SuperUserRightsFactory.getInstance();
return createUser(superUserRightsFactory, name, address,
identification, contactInformation);
}
/**
* General Method that will create any type of User.
*
* @param factory
* @param name
* @param address
* @param identification
* @param contactInformation
* @return
*/
private static User createUser(UserWithRightsFactory factory,
Name name,
Address address,
Identification identification,
ContactInformation contactInformation){
System.out.println("Factory class: " + factory +
" created user: " + name.getFirstName());
User user = factory.createUser();
user.setName(name);
user.setAddress(address);
user.setIdentification(identification);
user.setContactInformation(contactInformation);
return user;
}
}
