
Factory Pattern in Java
The Factory pattern is a creational design pattern used to centralize object creation logic. In Java, it helps client code ask for an object without knowing the concrete class that will be instantiated behind the scenes.
Factory Design Pattern is used when we have a superclass with multiple subclasses and based on input, we need to return one of the sub-class. This pattern takes out the responsibility of instantiation of a class from the client program to the factory class.
A Factory Pattern is one of the core design principles to create an object. This allows clients to create objects of a library in a way such that it doesn’t have tight coupling with the class hierarchy of the library.
This tutorial is a part of Creational Design Pattern Series. Take a look at other Creational Design Patterns:
- Singleton Creational Design Pattern Java Explained [6 Code Example]
- Factory Pattern in Java: Explanation and Example
- Factory Method Pattern in Java: Explanation and Example
- Abstract Factory Pattern in Java: Explanation and Example
- Builder Pattern in Java: Explanation and Example
- Prototype Pattern in Java: Explanation and Example
Factory Design Pattern Implementation
In our example, we will implement a logic to make a transaction in the Stock Exchange. In here, Client will have to call only the Concrete Factory Class Method with the listed company name to get the Company specific class. All inside class creation logic will be hidden from the client.
If you want the next step after simple factories, compare this with Factory Method Pattern in Java: Explanation and Example.
A Super-Class (Interface or Abstract Class)
Factory Design Pattern requires to have a Super Class which will be extended or inherited by the final product subclasses. In our example, we are using an abstract class Stock which has two abstract methods, buyShares(), and sellShares().
package com.adevguide.java.designpatterns.factory;
public abstract class Stock {
public abstract void buyShares(int n);
public abstract void sellShares(int n);
// implemented method
public void exchangeInfo() {
System.out.println("You are making Transactions at NASDAQ");
}
}
Sub-Classes
We have implemented three subclasses: AppleStock, AmazonStock, and GoogleStock. All subclasses have to implement superclass unimplemented classes. The implementation logic of these methods can be anything; only specific to class.
package com.adevguide.java.designpatterns.factory;
public class AppleStock extends Stock {
@Override
public void buyShares(int n) {
System.out.println("Congrats!! You have successfully bought " + n + " Apple Shares.");
}
@Override
public void sellShares(int n) {
System.out.println("Congrats!! You have successfully sold " + n + " Apple Shares.");
}
}
package com.adevguide.java.designpatterns.factory;
public class AmazonStock extends Stock {
@Override
public void buyShares(int n) {
System.out.println("Congrats!! You have successfully bought " + n + " Amazon Shares.");
}
@Override
public void sellShares(int n) {
System.out.println("Congrats!! You have successfully sold " + n + " Amazon Shares.");
}
}
package com.adevguide.java.designpatterns.factory;
public class GoogleStock extends Stock {
@Override
public void buyShares(int n) {
System.out.println("Congrats!! You have successfully bought " + n + " Google Shares.");
}
@Override
public void sellShares(int n) {
System.out.println("Congrats!! You have successfully sold " + n + " Google Shares.");
}
}
Enum Class for Company Name
package com.adevguide.java.designpatterns.factory;
public enum StockCompany {
APPLE,
GOOGLE,
AMAZON,
MICROSOFT;
}
Factory Class
Factory class StockFactory can be a singleton or can contain a static method getStock() which will be exposed to the client for Stock Class creation.
package com.adevguide.java.designpatterns.factory;
public class StockFactory {
public Stock getStock(StockCompany company) {
Stock stock;
switch (company) {
case APPLE:
stock = new AppleStock();
break;
case GOOGLE:
stock = new GoogleStock();
break;
case AMAZON:
stock = new AmazonStock();
break;
default:
throw new IllegalArgumentException("The stock is not listed in the market yet.");
}
stock.exchangeInfo();
return stock;
}
}
The factory method getStock(StockCompany company) accepts one parameter i.e company, depending on which it will decide which class object to return.
Client Class
Let’s create a Client that will demonstrate the implementation of the factory design pattern.
package com.adevguide.java.designpatterns.factory;
public class Client {
public static void main(String\[\] args) {
try {
SuperStockFactory stockFactory = new StockFactory();
Stock appleStock = stockFactory.getStock(StockCompany.APPLE);
appleStock.buyShares(10);
System.out.println("\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*");
Stock amazonStock = stockFactory.getStock(StockCompany.AMAZON);
amazonStock.sellShares(20);
System.out.println("\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*");
Stock microsoftStock = stockFactory.getStock(StockCompany.MICROSOFT);
microsoftStock.buyShares(10);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Output:
You are making Transactions at NASDAQ Congrats!! You have successfully bought 10 Apple Shares. ******************************** You are making Transactions at NASDAQ Congrats!! You have successfully sold 20 Amazon Shares. ******************************** java.lang.IllegalArgumentException: The stock is not listed in the market yet. at com.adevguide.java.designpatterns.factory.StockFactory.getStock(StockFactory.java:24) at com.adevguide.java.designpatterns.factory.Client.main(Client.java:22)
Notice that the client is calling the same factory method every time with a different company name, and the factory method is returning a different class as per the input parameter.
When to use the Factory Design Pattern?
- We can use this design when we want to delegate object instantiation to subclass. We would want to do this when we have product inheritance hierarchy and the possibility of the future addition to that.
Advantages of using Factory Design Pattern
- Factory Design pattern provides an approach to code for interface rather than implementation.
- That means the code interacts solely with the resultant interface or abstract class so that it will work with any classes that implement that interface or that extends that abstract class. For example, we can easily change AppleStock class implementation because the client program is unaware of this.
- Factory pattern provides abstraction between implementation and client classes through inheritance.
Real-World Example of Factory Design Pattern
java.util.Calendar,ResourceBundle, andNumberFormatgetInstance()methods use the Factory pattern.valueOf()method in wrapper classes like Boolean, Integer, etc.
Factory Design Pattern Source Code
You can find the complete source code of this tutorial in our GitHub repository.
References
https://www.journaldev.com/1392/factory-design-pattern-in-java