Understanding the Factory Method Design Pattern

Sangeeta Gupta
Lean In Women In Tech India
7 min readOct 29, 2018

Design Patterns are well proven and tested reusable solutions for recurring design problems in Object Oriented Software Development. These solutions ensure the development of highly cohesive modules with minimum coupling for our systems.

Factory Method Design Pattern , also known as the Virtual Constructor, is one of such many existing solutions dealing with object creation mechanisms. It intends at “ defining an interface for object creation but allows the subclasses decide which class of objects to instantiate.” There are four participants involved in this pattern who actively collaborate with one another during program execution.

  1. Product : it defines an abstract blueprint of objects the factory method creates.
  2. Concrete Product : sub-classes product and is the actual blueprint of objects which is created.
  3. Creator : it declares the factory method, which returns an object of type Product.
  4. ConcreteCreator : it overrides the factory method declared in Creator to return an instance of a ConcreteProduct.

This Pattern is useful in scenarios wherein it is difficult to anticipate which class of objects is to be created and used in our system. Let us try to analyze one such scenario and apply it for the same:

In today’s world Instagram seems to be an inseparable part of our lives. May it be sharing stories from our recent road trip or our voicing out our opinions, Instagram acts as a Doraemon fulfilling all our wishes. But as a developer have we ever thought of how Instagram, as an application actually deals with the changing moods and wants of the user? Let us focus at one of its functionalities and try to think from a developer’s perspective.

We will be focusing on the Instagram Story feature.

As an Instagram user, at a time, one can share a typed text, clicked image, recorded video as their story.

This means at any given point of time when a user is sharing a story, any one of these is being generated and used. But images, videos and text seem to be quite different from one another when it comes to the implementation of how it is being displayed or its content is being set. For example, while displaying a text story, we are concerned about the textual content, font styles etc while for a video the duration, start and end point are an important concern.

Product :

Each one of the above is also similar in the manner that it serves as a medium for conveying some visible information from the user’s end to the world. Instagram also allows us to resize and add location, stickers etc to our visible content. Thereby we can have an abstract class View providing a blueprint for our visible content with two abstract methods for display and setting the same.

/*
*The Product class which defines the type of objects that the
*factory method creates.
*/
abstract public class View {
// constants
private static final float MATCH_PARENT_WIDTH = 300.5f;
private static final float MATCH_PARENT_HEIGHT = 600.10f;

//attributes of visual content
float width, height;
String filter, sticker, location;
//abstract methods
abstract public void displayMedia();
abstract public void setContentForMedia(String content);
//default setting for any Story content
View() {
this.width = MATCH_PARENT_WIDTH;
this.height = MATCH_PARENT_HEIGHT;
filter = "normal";
sticker = "none";
location = "none";

}

// methods to change default values for attributes
public void setSize(float height, float width) { ... }

public void setFilterEffect(String filter) { ... }

public void setSticker(String sticker) { ... }

public void setLocation(String location) { ... }
}

Concrete Product :

This class can now be extended by TextView , VideoView and ImageView to create concrete blueprints for the three different kinds of content. Below are the set of observations made from the actual Instagram application :

  1. In Instagram, file source or clicked content is expected for images and videos while for text, the typed content is required.
  2. By default, the first 30 seconds of video is selected for our story. However, there is also a provision to select any part of a video greater than 30 seconds by specifying the start point.
  3. The text comes with a default setting for its font color and font type, but Instagram also allows user to customize it.

Keeping the above in mind, let’s create our classes!

/*
*Serves as a Concrete Product for by extending the Product class,
*View (for text)
*/
public class TextView extends View {

//attributes of TextView
String text, textColor, textType;
//default settings for Text Story content
TextView(String text) {
super();
this.text = text;
textColor = "black";
textType = "Classic";
}

//overriding the methods declared in View class.
@Override
public void displayMedia() {
//to display the text view.
System.out.println("Text: " + text + "Text Color: " + textColor + " Text Type: " + textType + "Filter : " + filter + " width: " + width + " height: " + height);
}

@Override
public void setContentForMedia(String content) {
//to set the content for the text view.
this.text = content;
}

//methods to change default values of TextView attributes
public void setTextColor(String textColor) { ... }

public void setText(String text) { ... }

public void setTextType(String textType) { ... }
}
/*
*Serves as a Concrete Product by extending the Product class,
*View (for video)
*/

public class
VideoView extends View {

//attributes of VideoView
String source,trimLength;
//default settings for Video Story content
VideoView(String source){
super();
this.source = source;
trimLength = "0 - 0:30";
}
//overriding the methods declared in View class.
@Override
public void displayMedia(){
//to display the video view
System.out.println("Source : " + source + "Duration: " + trimLength + "Filter : " + filter + " width: " + width + " height: " + height );
}

@Override
public void setContentForMedia(String content){
//to set the contents for the video view
this.source = content;
}
//method to change default clip start and end point for VideoView
public void setTrimLength(int startPoint) { ... }
}
/*
*Serves as a Concrete Product by extending the Product class,
* View (for image)
*/

public class
ImageView extends View {

//attribute of ImageView
String source;
//default settings for Image Story content
ImageView(String source){
super();
this.source = source;
}

//overriding the methods declared in View class.
@Override
public void displayMedia(){
//to display the image view.
System.out.println("Source : " + source + "Filter : " + filter + " width: " + width + " height: " + height );
}

@Override
public void setContentForMedia(String content){
//to set the content for the image view.
this.source = content;
}
}

Creator :

Moving ahead, we now require a Story interface for declaring the fixed duration and methods for sharing, removing, saving and our stories. This is the interface containing the factory method for generating objects of type View.

/*
*The Creator which declares the factory method returning an
* object of type View
*/

public interface
Story {

int duration = 30;

public View save();
public void publish();
public void remove();

//factory method
public View createViewForStory(String typeOfView,String content);

}

Concrete Creator :

Story interface can now be implemented by our InstagramStory class to override the factory method and provide a logic to instantiate a TextView, VideoView or ImageView object based on user selection and preference !

/*
*Serves as a Concrete Creator which overrides methods declared in
*the Creator class
*/

public class
InstagramStory implements Story {

//attributes
String viewGroup;
View view;
//default setting of story visibility
InstagramStory(){
viewGroup = "public";
}

//factory method for instantiating an object which is of type
View based on the type of view to be created and its content.

@Override
public View createViewForStory(String typeOfView, String content){

View view ;
typeOfView = typeOfView.trim().toLowerCase();

if(typeOfView.equals("image")){
view = new ImageView(content);
} else {
if(typeOfView.equals("video")){
view = new VideoView(content);
}
else if(typeOfView.equals("text")){
view = new TextView(content);
} else {
view = null;
}
}

return view;
}

//other methods to be overriden from the Story Interface
public View save() { ... }

public void publish() { ... }

public void remove() { ... }
}

Here, in Factory Pattern, as we are directly dealing with the View class instead of its sub classes, we can work with any user defined child classes of View. This also increases the extensibility of our code as we can later create sub classes of View for Boomerangs, Live etc and alter our factory method to implement the same in our Instagram Story !

Output :

Now, let’s look at the output for our code :

Here is the Github link for this code : https://github.com/sangeetagupta2068/FactoryDesignPattern

Thank you for reading this article !

--

--

Sangeeta Gupta
Lean In Women In Tech India

User Advocacy @ Dataiku | State of Indian Community Management 2021 | Meta Certified Community Manager