Factory Pattern

It is a creational pattern as this pattern deals with the best ways to create an object.

Let’s look into the use case below

We are developing an application which has to get data from third party and display it in our website.

Third party data could be in the form of Excel ,text file or anything which can change later.

Lets create a class for each data type representation

DataFromThirdPartyExcel.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.kb.factory.problem;
 
public class DataFromThirdPartyExcel {
    
    void getData(){
        System.out.println("logic to get excel data from third party");
        
    }
    
    void display(){
        System.out.println("logic to display excel data");
    }
 
}
package com.kb.factory.problem;

public class DataFromThirdPartyExcel {
	
	void getData(){
		System.out.println("logic to get excel data from third party");
		
	}
	
	void display(){
		System.out.println("logic to display excel data");
	}

}

DataFromThirdPartyTextFile.java

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.kb.factory.problem;
 
public class DataFromThirdPartyTextFile {
    void getData(){
        System.out.println("logic to get text file data from third party");
        
    }
    
    void display(){
        System.out.println("logic to display text file data");
    }
 
}
package com.kb.factory.problem;

public class DataFromThirdPartyTextFile {
	void getData(){
		System.out.println("logic to get text file data from third party");
		
	}
	
	void display(){
		System.out.println("logic to display text file data");
	}

}

Client.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.kb.factory.problem;
 
public class Client {
 
    public static void main(String[] args) {
        //To get Text data
        getDataFormThirdPartyAndDisplay("text");
        
        //To get Excel data
        getDataFormThirdPartyAndDisplay("excel");
 
    }
    
    
    static void getDataFormThirdPartyAndDisplay(String dataType){
        if(dataType.equalsIgnoreCase("text")){
            DataFromThirdPartyTextFile textFile = new DataFromThirdPartyTextFile();
            textFile.getData();
            textFile.display();
        }
        else if(dataType.equalsIgnoreCase("excel")){
            DataFromThirdPartyExcel thirdPartyExcel = new DataFromThirdPartyExcel();    
            thirdPartyExcel.getData();
            thirdPartyExcel.display();
        }
        else
            System.out.println("invalid data type");
            
    }
 
}
package com.kb.factory.problem;

public class Client {

	public static void main(String[] args) {
		//To get Text data
		getDataFormThirdPartyAndDisplay("text");
		
		//To get Excel data
		getDataFormThirdPartyAndDisplay("excel");

	}
	
	
	static void getDataFormThirdPartyAndDisplay(String dataType){
		if(dataType.equalsIgnoreCase("text")){
			DataFromThirdPartyTextFile textFile = new DataFromThirdPartyTextFile();
			textFile.getData();
			textFile.display();
		}
		else if(dataType.equalsIgnoreCase("excel")){
			DataFromThirdPartyExcel thirdPartyExcel = new DataFromThirdPartyExcel();	
			thirdPartyExcel.getData();
			thirdPartyExcel.display();
		}
		else
			System.out.println("invalid data type");
			
	}

}

Now look at the client code which has tight coupling with the excel class and text file class.

In future if we want to add one more data representation say PDF then again we have to go to the client code and change the behavior by adding one more else if condition.

Like

1
2
3
4
5
else if(dataType.equalsIgnoreCase("pdf")){
            DataFromThirdPartyPDF thirdPartypPdf = new DataFromThirdPartyPdf(); 
            thirdPartypPdf.getData();
            thirdPartypPdf.display();
        }
else if(dataType.equalsIgnoreCase("pdf")){
			DataFromThirdPartyPDF thirdPartypPdf = new DataFromThirdPartyPdf();	
			thirdPartypPdf.getData();
			thirdPartypPdf.display();
		}

So we are tending to change client code for every business needs changes.

So why can’t we separate this changing behavior and keep in some separate place.

Yes that separate place we call it as a Factory.

Factory pattern separates the object creation code (in fact frequently changing code) and put it in a place apart from client code.

Lets see how can we achieve this
Factory pattern

develop interface DataFromThirdParty.java

1
2
3
4
5
6
package com.kb.factory.solution;
 
public interface DataFromThirdParty {
    void getData();
    void display();
}
package com.kb.factory.solution;

public interface DataFromThirdParty {
	void getData();
	void display();
}

DataFromThirdPartyExcel.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.kb.factory.solution;
 
public class DataFromThirdPartyExcel implements DataFromThirdParty {
    
    public void getData(){
        System.out.println("logic to get excel data from third party");
        
    }
    
    public void display(){
        System.out.println("logic to display excel data");
    }
 
}
package com.kb.factory.solution;

public class DataFromThirdPartyExcel implements DataFromThirdParty {
	
	public void getData(){
		System.out.println("logic to get excel data from third party");
		
	}
	
	public void display(){
		System.out.println("logic to display excel data");
	}

}

DataFromThirdPartyTextFile.java

1
2
3
4
5
6
7
8
9
10
11
12
package com.kb.factory.solution;
 
public class DataFromThirdPartyTextFile  implements DataFromThirdParty {
    public void getData(){
        System.out.println("logic to get text file data from third party");
        
    }
    
    public void display(){
        System.out.println("logic to display text file data");
    }
}
package com.kb.factory.solution;

public class DataFromThirdPartyTextFile  implements DataFromThirdParty {
	public void getData(){
		System.out.println("logic to get text file data from third party");
		
	}
	
	public void display(){
		System.out.println("logic to display text file data");
	}
}

Most important is our factory code DataFromThirdPartyFactory.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.kb.factory.solution;
 
public class DataFromThirdPartyFactory {
    
    DataFromThirdParty getDataFromThirdParty(String dataType){
        if(dataType.equalsIgnoreCase("text")){
            return new DataFromThirdPartyTextFile();
            
        }
        else if(dataType.equalsIgnoreCase("excel")){
            return new DataFromThirdPartyExcel();   
            
        }
        else
            System.out.println("invalid data type");
        return null;
        
    }
}
package com.kb.factory.solution;

public class DataFromThirdPartyFactory {
	
	DataFromThirdParty getDataFromThirdParty(String dataType){
		if(dataType.equalsIgnoreCase("text")){
			return new DataFromThirdPartyTextFile();
			
		}
		else if(dataType.equalsIgnoreCase("excel")){
			return new DataFromThirdPartyExcel();	
			
		}
		else
			System.out.println("invalid data type");
		return null;
		
	}
}

Client.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.kb.factory.solution;
 
public class Client {
 
    public static void main(String[] args) {
        DataFromThirdParty dataFromThirdParty;
        
        DataFromThirdPartyFactory thirdPartyFactory = new DataFromThirdPartyFactory();
        
        //To get Text data
        dataFromThirdParty = thirdPartyFactory.getDataFromThirdParty("text");
        dataFromThirdParty.getData();
        dataFromThirdParty.display();
        
        //To get Excel data
        dataFromThirdParty = thirdPartyFactory.getDataFromThirdParty("excel");
        dataFromThirdParty.getData();
        dataFromThirdParty.display();
        
 
    }
}
package com.kb.factory.solution;

public class Client {

	public static void main(String[] args) {
		DataFromThirdParty dataFromThirdParty;
		
		DataFromThirdPartyFactory thirdPartyFactory = new DataFromThirdPartyFactory();
		
		//To get Text data
		dataFromThirdParty = thirdPartyFactory.getDataFromThirdParty("text");
		dataFromThirdParty.getData();
		dataFromThirdParty.display();
		
		//To get Excel data
		dataFromThirdParty = thirdPartyFactory.getDataFromThirdParty("excel");
		dataFromThirdParty.getData();
		dataFromThirdParty.display();
		

	}
}

Now client using factory object to get the required object.

Now if we want to add new functionality to get data in the PDF form, then it needs no change at client with respect to data representation logic . only client has to include a call to the PDF data type.

Lets see above change in factory pattern

Obviously Change in factory pattern means change inside factory class only.

Create a new functionality but implement it with the interface DataFromThirdParty

As we should do program to Interface not program to Implementation.

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.kb.factory.solution;
 
public class DataFromThirdPartyPDF implements DataFromThirdParty{
    public void getData(){
        System.out.println("logic to get pdf file data from third party");
        
    }
    
    public void display(){
        System.out.println("logic to display pdf file data");
    }
 
}
package com.kb.factory.solution;

public class DataFromThirdPartyPDF implements DataFromThirdParty{
	public void getData(){
		System.out.println("logic to get pdf file data from third party");
		
	}
	
	public void display(){
		System.out.println("logic to display pdf file data");
	}

}

Now see how Factory class gets one extra else if statement

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.kb.factory.solution;
 
public class DataFromThirdPartyFactory {
    
    DataFromThirdParty getDataFromThirdParty(String dataType){
        if(dataType.equalsIgnoreCase("text")){
            return new DataFromThirdPartyTextFile();
            
        }
        else if(dataType.equalsIgnoreCase("excel")){
            return new DataFromThirdPartyExcel();   
            
        }
        
        else if(dataType.equalsIgnoreCase("pdf")){
            return new DataFromThirdPartyPDF();
        }
        else
            System.out.println("invalid data type");
        return null;
        
    }
}
package com.kb.factory.solution;

public class DataFromThirdPartyFactory {
	
	DataFromThirdParty getDataFromThirdParty(String dataType){
		if(dataType.equalsIgnoreCase("text")){
			return new DataFromThirdPartyTextFile();
			
		}
		else if(dataType.equalsIgnoreCase("excel")){
			return new DataFromThirdPartyExcel();	
			
		}
		
		else if(dataType.equalsIgnoreCase("pdf")){
			return new DataFromThirdPartyPDF();
		}
		else
			System.out.println("invalid data type");
		return null;
		
	}
}

That’s it new functionality has been implemented without client knows about it.

Now client can use this new functionality just by calling same factory method but passing different string for pdf as below

1
2
3
dataFromThirdParty = thirdPartyFactory.getDataFromThirdParty("pdf");
        dataFromThirdParty.getData();
        dataFromThirdParty.display();
dataFromThirdParty = thirdPartyFactory.getDataFromThirdParty("pdf");
		dataFromThirdParty.getData();
		dataFromThirdParty.display();

So complete client code is

Client.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.kb.factory.solution;
 
public class Client {
 
    public static void main(String[] args) {
        DataFromThirdParty dataFromThirdParty;
        
        DataFromThirdPartyFactory thirdPartyFactory = new DataFromThirdPartyFactory();
        
        //To get Text data
        dataFromThirdParty = thirdPartyFactory.getDataFromThirdParty("text");
        dataFromThirdParty.getData();
        dataFromThirdParty.display();
        
        //To get Excel data
        dataFromThirdParty = thirdPartyFactory.getDataFromThirdParty("excel");
        dataFromThirdParty.getData();
        dataFromThirdParty.display();
        
 
        //To get PDF data
        dataFromThirdParty = thirdPartyFactory.getDataFromThirdParty("pdf");
        dataFromThirdParty.getData();
        dataFromThirdParty.display();
 
    }
}
package com.kb.factory.solution;

public class Client {

	public static void main(String[] args) {
		DataFromThirdParty dataFromThirdParty;
		
		DataFromThirdPartyFactory thirdPartyFactory = new DataFromThirdPartyFactory();
		
		//To get Text data
		dataFromThirdParty = thirdPartyFactory.getDataFromThirdParty("text");
		dataFromThirdParty.getData();
		dataFromThirdParty.display();
		
		//To get Excel data
		dataFromThirdParty = thirdPartyFactory.getDataFromThirdParty("excel");
		dataFromThirdParty.getData();
		dataFromThirdParty.display();
		

		//To get PDF data
		dataFromThirdParty = thirdPartyFactory.getDataFromThirdParty("pdf");
		dataFromThirdParty.getData();
		dataFromThirdParty.display();

	}
}

The same Factory pattern has been used in spring container to get the required object using XML.

That’s all about factory design pattern.

About the Author

Karibasappa G C (KB)
Founder of javainsimpleway.com
I love Java and open source technologies and very much passionate about software development.
I like to share my knowledge with others especially on technology πŸ™‚
I have given all the examples as simple as possible to understand for the beginners.
All the code posted on my blog is developed,compiled and tested in my development environment.
If you find any mistakes or bugs, Please drop an email to kb.knowledge.sharing@gmail.com

Connect with me on Facebook for more updates

Share this article on

Comment (9)

  1. Hello

    I really liked your blog.however in this post i would like to add something ,

    you have mentioned there that

    *How we create object in Java ?

    Yes using constructor , and we should not allow users to access constructor and execute it every time they try to. *

    I believe this statement is completely wrong. constructor is executed that does not mean object is created. object is create only using new operator and constructor is executed to initialize the instance variable.

    Kindly correct it.. πŸ™‚

    thanks again.

    1. Karibasappa G C (KB)
      Karibasappa G C (KB)

      Thanks PushP for bringing this into discussion!!

      Let me try to make you understand the below line
      we should not allow users to access constructor and execute it every time they try to.

      If we are making someone to access constructor I mean execute constructor multiple times it just creates new object according to Java concept.

      How ?
      you know that constructors don’t have names right,so the only we to make the constructor execution is by creating an object using new.
      I agree that constructor execution and object creation are different activities but my point here is when you allow someone to execute the constructor multiple times, it means you are calling constructors multiple times because there is no other way to execute the constructors.
      Note:going through programmatically not through reflection and all.

      your opinion
      constructor is executed that does not mean object is created , object is created only using new operator and constructor is executed to initialize the instance variable

      my understanding on your opinion
      if I go by English i agree with this sentence , but going by Java concept i can not agree with this.
      Because when constructor is executed it means that you have called it using new class_name(), it means one object gets created in Java.
      I am not saying constructor execution and object creation are synonyms but what i am saying is they are mutually dependent.

      So my point here is simple,
      we should not allow users create object multiple times which is same as we should not allow users to execute the constructors multiple times.

      preventing constructor execution is same as not allowing someone to create an object.

      Happy to hear your inputs again and Thank you so much !!

  2. karibasappagc

    Hi Mani,,,

    I have added subscribe option on the right sidebar, you can subscribe there to receive the updates πŸ™‚

    Thank you once again…and welcome for your comments always.

  3. karibasappagc

    Hi Mani, Its really very good notice…

    I forgot to add clone and also i didn’t add one more approach using ENUM.

    But Reflection you are right , i didnt notice this situation. but its good to cover that as well.

    so i will edit this post sometime to include all the above scenarios.

    Thanks a lot for reading , observing the things and suggesting.

    Keep Suggesting the posts during your free time πŸ™‚ Thank you once again…

  4. Manikandan Jayaraman

    Good one, KB πŸ™‚

    I can break your code using reflection though:
    ===
    // Access constructor using reflection
    Class clazz = FinalSingleton.class;
    Constructor cons = clazz.getDeclaredConstructor();
    cons.setAccessible(true);
    FinalSingleton instanceThree = cons.newInstance();
    instanceThree.setX(300);
    System.out.println(“instanceThree.getX() :: “+instanceThree.getX());
    ===

    the above creates a new instance.you can avoid that by changig your constructor
    ===
    private FinalSingleton() {

    //If-block needed to avoid creation of another object using reflection
    /*if (LazyLoadFinalSingleton.SINGLETONINSTANCE != null) {
    throw new IllegalStateException(“Inside FinalSingleton(): instance already created.”);
    }*/

    x = 100;
    System.out.println(“Constructor Called. Instance created.”);
    }
    ===

    Also good to override clone method and throw clone not supported exception. You will never know where the loop hole is. πŸ™‚

Leave a Comment

  • You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code lang=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre lang="" extra="">

    • Please answer this simple challenge to post your valuable comment *