Factory Design Pattern: Notification System Implementation
Design Pattern

Factory Design Pattern: Notification System Implementation

S

Shivam Chauhan

26 days ago

The Factory Design Pattern is a creational pattern that provides an interface for creating objects in a superclass but allows subclasses to alter the type of objects that will be created. This pattern promotes flexibility and scalability in your codebase.

What is the Factory Design Pattern?

In object-oriented programming, the Factory Design Pattern defines an interface for creating an object but lets subclasses decide which class to instantiate. This pattern delegates the responsibility of object instantiation to subclasses, promoting loose coupling and enhancing code maintainability.

When to Use the Factory Design Pattern

Consider using the Factory Design Pattern when:

  • The exact type of object to be created isn't known until runtime.
  • You want to provide a library of objects that doesn't expose implementation details.
  • You need to manage and maintain a group of related objects.

Implementing the Factory Design Pattern

Here's how you can implement the Factory Design Pattern:

java
// Product interface
public interface Product {
    void use();
}

// Concrete Product A
public class ConcreteProductA implements Product {
    @Override
    public void use() {
        System.out.println("Using ConcreteProductA");
    }
}

// Concrete Product B
public class ConcreteProductB implements Product {
    @Override
    public void use() {
        System.out.println("Using ConcreteProductB");
    }
}

// Factory class
public class ProductFactory {
    public static Product createProduct(String type) {
        switch (type) {
            case "A":
                return new ConcreteProductA();
            case "B":
                return new ConcreteProductB();
            default:
                throw new IllegalArgumentException("Unknown product type");
        }
    }
}

// Client code
public class Client {
    public static void main(String[] args) {
        Product product = ProductFactory.createProduct("A");
        product.use(); // Output: Using ConcreteProductA
    }
}

In this example:

  • Product is the interface that defines the operations that all concrete products must implement.
  • ConcreteProductA and ConcreteProductB are concrete implementations of the Product interface.
  • ProductFactory is responsible for creating instances of Product based on the provided type.
  • The client code uses the factory to create objects without knowing the exact class of the object that will be created.

Advantages of the Factory Design Pattern

  • Encapsulation: Encapsulates the object creation process, reducing the complexity in client code.
  • Flexibility: Makes it easy to introduce new types of products without changing existing client code.
  • Loose Coupling: Promotes loose coupling between client code and the classes of objects that need to be instantiated.

Real-World Example: Notification System

Consider a notification system that sends messages via different channels like Email, SMS, and Push Notifications. Using the Factory Design Pattern, you can create a NotificationFactory that instantiates the appropriate notification sender based on input parameters.

java
// Notification interface
public interface Notification {
    void notifyUser();
}

// Email Notification
public class EmailNotification implements Notification {
    @Override
    public void notifyUser() {
        System.out.println("Sending an email notification");
    }
}

// SMS Notification
public class SMSNotification implements Notification {
    @Override
    public void notifyUser() {
        System.out.println("Sending an SMS notification");
    }
}

// Push Notification
public class PushNotification implements Notification {
    @Override
    public void notifyUser() {
        System.out.println("Sending a push notification");
    }
}

// Notification Factory
public class NotificationFactory {
    public static Notification createNotification(String channel) {
        switch (channel) {
            case "EMAIL":
                return new EmailNotification();
            case "SMS":
                return new SMSNotification();
            case "PUSH":
                return new PushNotification();
            default:
                throw new IllegalArgumentException("Unknown channel " + channel);
        }
    }
}

// Client code
public class Client {
    public static void main(String[] args) {
        Notification notification = NotificationFactory.createNotification("EMAIL");
        notification.notifyUser(); // Output: Sending an email notification
    }
}

In this scenario, the NotificationFactory determines the type of notification to create based on the input parameter, allowing the client code to remain agnostic of the specific notification classes.

Now you know what actually Factory Design Pattern is, then why not try solving this problem yourself

Conclusion

The Factory Design Pattern is a powerful tool that promotes flexibility and scalability by delegating object creation to subclasses. By implementing this pattern, developers can create more maintainable and extensible codebases.

For hands-on practice with the Factory Design Pattern and other design patterns, consider exploring more problems at Coudo AI, where practical exercises and AI-driven feedback can enhance your learning experience.

About the Author

S

Shivam Chauhan

Sharing insights about system design and coding practices.