Over the course of this article, we will examine one of the most commonly used patterns, the Factory method pattern in java.

Software systems undergo constant changes and they are unstable. We must consider to design where the objects and relationships are loosely coupled. Loose coupling is one of the most important characteristics in software design; this helps in extending new functions in the software without disturbing or doing no changes to the existing system.

“The Factory design pattern provides a way to use an instance as an object factory. The factory can return an instance of one of several possible classes in a class hierarchy, depending on the data provided to it.”

Java Factory pattern belongs to the creational family of design patterns that govern the object instantiation process. The Factory pattern is a grouped into the Simple Factory, Factory Method and Abstract Factory patterns. We will taper the context of this tutorial to Simple Factory and Factory method design pattern.

  1. Simple Factory: Simple factory isn’t actually a design pattern; its more of a programming technique often used to encapsulate the object instantiation process.
  2. Factory Method: Defines an interface for creating an object, but let’s the classes that implement the interface decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses.
  3. Abstract Factory: Provides an interface for creating families of related or dependent objects without specifying their concrete classes.

Benefits of Factory design pattern

  1. The client does not need to know every subclass of objects it must create. It only need one reference to the abstract class/interface and the factory object.
  2. The factory encapsulate the creation of objects. This can be useful if the creation process is very complex.

Simple Factory Pattern

Spice Digital Inc. is one of the top smartphone manufacturers in India. They are pioneer in manufacturing and distributing smartphones in indian market. For now they have two successful products SpiceFire and SpiceBolt. The produceMobile() method is working well which produce two different mobiles based on their model number. Let us have a look into the current implementation of produceMobile() method.

public SpiceMobile produceMobile(String model) {
		SpiceMobile mobile = null;

		if (model.equalsIgnoreCase("SpiceBolt")) {
			mobile = new SpicePlus();
		} else if (model.equalsIgnoreCase("SpiceFire")) {
			mobile = new SpiceBolt();
		}
		mobile.prepare();
		mobile.bundle();
		mobile.label();

		return mobile;
}

SpiceMobile implementation

public abstract class SpiceMobile {
	public abstract void prepare();
	public abstract void bundle();
	public abstract void label();
}

public class SpiceFire extends SpiceMobile {
	@Override
	public void prepare() {
	}

	@Override
	public void bundle() {
	}

	@Override
	public void label() {
	}
}

public class SpiceBolt extends SpiceMobile {

	@Override
	public void prepare() {
	}

	@Override
	public void bundle() {
	}

	@Override
	public void label() {
	}
}

Problems with above implementation

  1. The above implementation is working well and everyone are happy. However, at some point of time company want to release another new model to market, they need to change the produceMobile() method code.
  2. Design is not extensive and it is closed for modification.
  3. Adds more complexity to refactor code each time new products added.

Factory Method Design Pattern Example

The above example is working great to deal for producing mobiles. However, we have outlined some of the problems above on the above approach. Now let us add some more complexity to the above requirements.

Spice Digital Inc. company now decided to makes their global presence. They want to extend their business to London and NewYork location. Looking at the market interest, London factory will produce only SpiceBolt and SpiceFire model and New York will produce SpiceFire and SpicePlus. Now the usecase is becoming fairly complex. Let us have a glance at the below class diagram that using Factory method design pattern.

Factory Method Design Pattern

SpiceMobile.java

public abstract class SpiceMobile {
	public double price;
	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	public abstract void prepare();

	public abstract void bundle();

	public abstract void label();
}

Now, let us create three different Spice mobile implementation. For demonstration purpose, we have three simple implementation i.e. SpiceBolt, SpiceFire and SpicePlus. All three classes are similar so we don’t have listed them all.

SpiceBolt.java

public class SpiceBolt extends SpiceMobile {

	@Override
	public void prepare() {
	}

	@Override
	public void bundle() {
	}

	@Override
	public void label() {
	}
}

MobileFactory.java

public abstract class MobileFactory {

	public abstract SpiceMobile constructMobile(String model);

	/**
	 * Defines the process to product mobile. This implementation should'nt be
	 * be changed by clients
	 * 
	 * @param model
	 * @return SpiceMobile
	 */
	public SpiceMobile produceMobile(String model) {

		SpiceMobile mobile = constructMobile(model);
		mobile.prepare();
		mobile.bundle();
		mobile.label();

		return mobile;
	}
}

LondonMobileFactory.java

/**
 * London mobile factory is specialized and only sale Spice3D and SpiceHD.
 */
public class LondonMobileFactory extends MobileFactory {

	@Override
	public SpiceMobile constructMobile(String model) {

		SpiceMobile mobile = null;

		if (model.equalsIgnoreCase("SpiceFire")) {
			mobile = new SpicePlus();
			mobile.setPrice(300);
		} else if (model.equalsIgnoreCase("SpiceBolt")) {
			mobile = new SpiceBolt();
			mobile.setPrice(400);
		}

		return mobile;
	}
}

NYMobileFactory.java

/**
 * New York mobile factory is specialized and only sale Spice3D and SpiceMono.
 */

public class NYMobileFactory extends MobileFactory {

	@Override
	public SpiceMobile constructMobile(String model) {
		
		SpiceMobile mobile = null;

		if (model.equalsIgnoreCase("SpiceFire")) {
			mobile = new SpicePlus();
			mobile.setPrice(200);
		} else if (model.equalsIgnoreCase("SpiceMono")) {
			mobile = new SpiceFire();
			mobile.setPrice(280);
		}

		return mobile;
	}
}

Client.java

public class Client {

	public static void main(String[] args) {

		MobileFactory factory = new LondonMobileFactory();
		SpiceMobile mobile = factory.produceMobile("SpiceHD");

		MobileFactory nyFactory = new NYMobileFactory();
		SpiceMobile mobile2 = factory.produceMobile("SpiceMono");

	}
}

Nilanchala

A blogger, a bit of tech freak and a software developer. He is a thought leader in the fusion of design and mobile technologies. He is the author of Xamarin Mobile Application Development for Android Book (goo.gl/qUZ0XV3), DZone MVB and founder of stacktips.com.

Related Articles

Join The Discussion

Please note: We reserve the right to delete comments that contains snarky remarks, offensive or off-topic. To know more read our comments policy.
  • lovroh

    thanks for this simplified explanation.. you rock!!

  • may be small finding : london factory doesn’t provide such class name spiceHd
    any good article thanks

  • Anil Nivargi

    nice explanation…

  • Anil Nivargi

    Thanks for good explanation…..