Improve your Factory Method Implementation

Eric Diaz
3 min readJul 3, 2022

This article builds on the Factory Design Pattern in Kotlin and Java — Made Easy and Simple article which covers the basics of the Factory Method. We continue the example of building a CarFactory below.

How a decent Factory method implementation looks

While this is a passable approach, there is room for improvement. Let’s review some of the areas of improvement below.

The CarFactory breaks the open-closed design principle.

The Open-Closed design principle state software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification. If we wanted to add another CarManufacturer and a new Car implementation, then we would have to change the code in the CarFactory to support the new Car. Instead we want to be able to continually extend CarFactory to provide more Car implementations.

The CarFactory has too many responsibilities.

The Single Responsibility design principle states every class, module, or function in a program should have one responsibility/purpose in a program. The CarFactory is constructing several subclasses of Car when ideally it should only be responsible for providing just one. In this example, each subclass of Car could have several dependencies and construction steps that would quickly make the getCarByManufacturer unscalable and unsustainable.

The CarFactory tightly couples every Car and CarManufacturer.

On the client-side, which is the BasicDealership, any changes or additions done to the CarFactory will always be made available to the client. Imagine we wanted to remove a Car implementation from one Dealership but not another. This would be impossible because the CarFactory couples the responsibilities of all the Car subclass creations which means if it’s removed from the getCarByManufacturer function, then its removed from all clients that depend solely on CarFactory. The client should be able to decide it’s own composition. The Dealership should be able to decide what CarFactories it wants to support.

How we improved the implementation

Below is the new and improved implementation of the CarFactory called BetterCarFactory. Let’s review some of the changes.

The BetterCarFactory (CarFactory improved)

The BetterCarFactory starts by being declared as an interface rather than a concrete class. This will allow subclasses to determine how to produce a Car and will still enforce the Single Responsibility principle and Factory method getCar().

The old CarFactory requires the CarManufacturer in its create method, while the BetterCarFactory does not. This is because the interface does not care what subclass of Car is being created, only that some subclass of Car is created.

The BetterCarFactory Subclasses

The BetterCarFactory subclasses now encapsulate their own specific Car creation implementations. This more maintainable and scalable as compared to the getCarByManufacturer function in the CarFactory which contained the implementation details of all the Car subclasses. New Car and BetterCarFactory implementations may be created without affecting other existing implementations.

The Dealership (Client)

The AdvancedDealership can now determine which Factories and Cars it wants to support. The old BasicDealership had access to only the Cars the CarFactory had available, which essentially made it impossible to compose different Dealerships based on the uniqueness of the Cars that are available. Now different Dealerships can be created with different sets of factories.

That’s it! Much more improved! You can find the example repository here! Follow me for more coding made simple content!

--

--