The factory method pattern is a creational pattern which provides an interface to create objects in a parent class. Subclasses of that class can override the method that creates the objects to change the type of object that will be created.
This way the creation of the objects is decoupled from the rest of the code.
Use the factory method pattern when:
You can find the full example source code here.
In the example I'm going to handle payments so I'm going to use the following interface:
interface Payment {
creditCard: number;
}
In this example, createPayment
is the abstract method that will be implemented by the subclasses. It could also be possible to have a default implementation of this method in the abstract class if you want to have some default setup.
Apart from this, I'm including the method completePayment
which will be common to all the objects created by the subclasses.
abstract class PaymentGateway {
public abstract createPayment(creditCard: number, ...args: any[]): Payment;
public completePayment(payment: Payment): void {
console.log(
`Payment with credit card ${payment.creditCard} successfully completed using the PaymentGateway`
);
}
}
In the example I will have PhysicalPayment
and OnlinePayment
.
interface PhysicalPayment extends Payment {
storeLocation: string;
}
interface OnlinePayment extends Payment {
email: string;
}
createPayment
method.As I have two different object types, I will create two new classes: PhysicalPaymentGateway
and OnlinePaymentGateway
.
class PhysicalPaymentGateway extends PaymentGateway {
public createPayment(
creditCard: number,
storeLocation: string
): PhysicalPayment {
return {
creditCard,
storeLocation,
};
}
}
class OnlinePaymentGateway extends PaymentGateway {
public createPayment(creditCard: number, email: string): OnlinePayment {
return {
creditCard,
email,
};
}
}
An example of how client code would create objects for the online variant:
const onlinePaymentGateway = new OnlinePaymentGateway();
const onlinePayment = onlinePaymentGateway.createPayment(
987654321,
"test@example.com"
);
onlinePaymentGateway.completePayment(onlinePayment);
An this is how the client would use the physical variant:
const physicalPaymentGateway = new PhysicalPaymentGateway();
const physicalPayment = physicalPaymentGateway.createPayment(
123456789,
"New York"
);
physicalPaymentGateway.completePayment(physicalPayment);
As always, make sure it makes sense to use this pattern in your application. Otherwise you could be introducing unnecessary complexity.