Table of Contents
ToggleWhen designing a payment system, it’s crucial to maintain flexibility and extensibility to accommodate various payment methods that may evolve over time. The Factory Design Pattern provides an elegant solution to dynamically create instances of different payment methods without tightly coupling the client code to specific implementations.
Let’s see How to apply Factory Design Pattern for Payment System? But first, let’s recap.
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 is useful when the creation of an object is complex, involves conditional logic, or needs to be delegated to subclasses.
Components of the Factory Design Pattern
- Product Interface: This defines the contract for the products created by the factory.
- Concrete Products: These are the specific implementations of the product interface.
- Creator (Factory) Interface: An interface that declares the factory method, which returns an object of the product interface.
- Concrete Creator: Implements the factory method to create and return concrete products.
How To Apply Factory Design Pattern For Payment System
Let’s delve into implementing Factory Design Pattern For Payment System step by step:
Step 1: Define Payment Interface
To begin, we establish a Payment interface that outlines the common behaviour expected from all payment methods. This abstraction allows us to interact with various payment types uniformly.
// Payment interface
public interface Payment {
void processPayment(double amount);
}
Step 2: Implement Concrete Payment Methods
In this step, we create concrete implementations for specific payment methods such as credit card payments and PayPal payments. Each implementation adheres to the Payment interface, ensuring consistency in how payments are processed.
// Concrete payment method: Credit Card
public class CreditCardPayment implements Payment {
@Override
public void processPayment(double amount) {
System.out.println("Processing credit card payment of $" + amount);
// Logic for processing credit card payment
}
}
// Concrete payment method: PayPal
public class PayPalPayment implements Payment {
@Override
public void processPayment(double amount) {
System.out.println("Processing PayPal payment of $" + amount);
// Logic for processing PayPal payment
}
}
Step 3: Create Payment Factory
The PaymentFactory acts as a central entity responsible for instantiating different payment methods based on provided criteria. It encapsulates the creation logic, promoting a clean separation of concerns.
// Payment factory
public class PaymentFactory {
public static Payment createPayment(String type) {
switch (type) {
case "credit_card":
return new CreditCardPayment();
case "paypal":
return new PayPalPayment();
default:
throw new IllegalArgumentException("Invalid payment type: " + type);
}
}
}
Step 4: Client Code Using Payment Factory
Finally, let’s demonstrate the usage of the PaymentFactory in client code. Here, we obtain instances of specific payment methods through the factory and perform payment processing operations.
// Client code
public class PaymentClient {
public static void main(String[] args) {
// Create a credit card payment
Payment creditCardPayment = PaymentFactory.createPayment("credit_card");
creditCardPayment.processPayment(100.00);
// Create a PayPal payment
Payment paypalPayment = PaymentFactory.createPayment("paypal");
paypalPayment.processPayment(50.00);
}
}
Complete Java Code To Apply Factory Design Pattern For Payment System
// Payment interface defining common behavior for all payment methods
public interface Payment {
void processPayment(double amount);
}
// Concrete implementation for credit card payment
public class CreditCardPayment implements Payment {
@Override
public void processPayment(double amount) {
// Logic for processing credit card payment
System.out.println("Processing credit card payment of $" + amount);
}
}
// Concrete implementation for PayPal payment
public class PayPalPayment implements Payment {
@Override
public void processPayment(double amount) {
// Logic for processing PayPal payment
System.out.println("Processing PayPal payment of $" + amount);
}
}
// Factory class responsible for creating instances of different payment methods
public class PaymentFactory {
public static Payment createPayment(String type) {
switch (type) {
case "credit_card":
return new CreditCardPayment();
case "paypal":
return new PayPalPayment();
default:
throw new IllegalArgumentException("Invalid payment type: " + type);
}
}
}
// Client class demonstrating the usage of the payment system
public class PaymentClient {
public static void main(String[] args) {
// Create a credit card payment
Payment creditCardPayment = PaymentFactory.createPayment("credit_card");
creditCardPayment.processPayment(100.00);
// Create a PayPal payment
Payment paypalPayment = PaymentFactory.createPayment("paypal");
paypalPayment.processPayment(50.00);
}
}
Conclusion
By leveraging the Factory Design Pattern, we achieve a modular and extensible payment system architecture. This pattern enables the dynamic creation of payment method instances, promoting code maintainability, scalability, and ease of integration with evolving business requirements.
Similar Posts
How Factory Design Pattern Is Used in Spring Boot?
Can We Use Factory Design Pattern in Dependency Injection?
What Is the Difference Between Factory and Abstract Factory Design Patterns?
When to Use Factory Design Pattern in Java?
FAQ
What is the main goal of the factory design pattern?
The main goal of the factory design pattern is to provide an interface for creating objects in a superclass, but allow subclasses to alter the type of objects that will be created. It promotes loose coupling by abstracting the object creation process from the client code.
What is factory design pattern with real time example?
A real-time example of the factory design pattern could be a software application that produces different types of documents, such as reports, spreadsheets, and presentations. Instead of having the client code directly instantiate each type of document (e.g., Report, Spreadsheet, Presentation), a DocumentFactory can be used. The DocumentFactory provides methods for creating different types of documents based on user input or other factors. This way, the client code only interacts with the factory to obtain instances of documents, without being concerned about their specific implementation details.
What are the types of factory pattern?
There are several variations of the factory pattern, including:
- Simple Factory: This is the most basic form of factory pattern where a factory class has methods for creating objects without exposing the instantiation logic to the client.
- Factory Method: In this pattern, a superclass provides an interface for creating objects, but allows subclasses to override the instantiation process to provide different implementations of the created objects.
- Abstract Factory: This pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. It defines a set of methods, each of which returns a different abstract product.
What is the benefit of factory pattern?
The benefits of using the factory pattern include:
- Encapsulation: It encapsulates the object creation process, hiding the implementation details of object creation from the client code.
- Flexibility: It allows for easy extension and modification of the object creation process, enabling the addition of new types of objects without modifying existing client code.
- Promotes Loose Coupling: It promotes loose coupling between the client code and the created objects, as the client code only interacts with the factory interface, not with the concrete classes directly.
- Centralized Control: It provides a centralized place (the factory) to manage the creation of objects, making it easier to maintain and refactor the code.