Factory Method: Design Pattern
Factory Method is a creational design pattern that provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created.
Problem:
Suppose you’re creating a sms notification service app. The bulk of your code lives in SmsNotification class but as the app became popular and business grew you also need to send notification via Email too. At present, most of your code is coupled to the SmsNotification class. Adding Email into the app would require making changes to the entire codebase. Moreover, if later you decide to add another type of Notification to the app, you will probably need to make all of these changes again.
As a result, you will end up with pretty nasty code, riddled with conditionals that switch the app’s behavior depending on the class of transportation objects.
The Factory Method separates product construction code from the code that actually uses the product. Therefore it’s easier to extend the product construction code independently from the rest of the code.
Solution:
The Factory Method pattern suggests that you replace direct object construction calls (using the new operator) with calls to a special factory method. Don’t worry: the objects are still created via the new operator, but it’s being called from within the factory method. Objects returned by a factory method are often referred to as products.
Get Debarshi Raj Basumatary’s stories in your inbox
Join Medium for free to get updates from this writer.
Common Interface/Product:
// 1. PRODUCT: the interface that all channels implement
public interface Channel {
void deliver(String message);
}Concrete Implementation: Developers define a specific product class corresponding to each distinct feature or type addition.
// 2. CONCRETE PRODUCTS: each class implements one delivery method
public class EmailChannel implements Channel {
@Override
public void deliver(String message) {
System.out.println("E-mail sent: " + message);
}
}
public class SmsChannel implements Channel {
@Override
public void deliver(String message) {
System.out.println("SMS sent: " + message);
}
}Abstract Creator Class: Defines the factory method that returns a Product object.
// 3. CREATOR: declares the factory method and uses the Product
public abstract class Notifier {
// FACTORY METHOD: subclasses must override it
protected abstract Channel createChannel();
// Business logic. It does NOT know the concrete class.
public void send(String message) {
Channel channel = createChannel(); // the subclass decides
channel.deliver(message); // use the Product interface
}
}Concrete Creators: Subclasses override the factory method to instantiate and return specific product variants. Developers create them for each specific type.
// 4. CONCRETE CREATORS: each one returns a different Product
public class EmailNotifier extends Notifier {
@Override
protected Channel createChannel() {
return new EmailChannel();
}
}
public class SmsNotifier extends Notifier {
@Override
protected Channel createChannel() {
return new SmsChannel();
}
}Finally Client creates the Email Notification Object.
// 5. CLIENT: works with the Creator type only
public class Main {
public static void main(String[] args) {
Notifier notifier = new EmailNotifier(); // change this one line
notifier.send("Your order is shipped."); // to switch the channel
}
}Pros and Cons:
Pros
- You avoid tight coupling between the creator and the concrete products.
- Single Responsibility Principle. You can move the product creation code into one place in the program, making the code easier to support.
- Open/Closed Principle. You can introduce new types of products into the program without breaking existing client code.
Cons
- The code may become more complicated since you need to introduce a lot of new subclasses to implement the pattern. The best case scenario is when you’re introducing the pattern into an existing hierarchy of creator classes.









