Introduction to Factory Pattern (1): Simple Factory Pattern

Nowadays, design patterns are not that popular to talk about. This could be related to the rapid iteration of web services, and the popularity of Micro Services. Design patterns were once considered useless dogma, thus as an anti-pattern, during the hype of Function Programming.

Of course, design patterns might have been thrown away as the essence of Object-Oriented Programming, because Functional Programming was preferred to OOP and was a hype during the time.

But if we think back, these design patterns are actually useful experiences extracted from practice. They do improve readability and scalability of programs to some extent. On the other hand, as well known conventions, design patterns deepen understanding between author and reader. In this sense, they can be considered as a medium of communication. Of course, this has to be used at correct scenarios. In terms of correct scenarios, we are talking about suitable scenarios — not using because we want to use, but for practical purpose.

In this blog post, I will introduce one of the most used design patterns: Factory Pattern, and talk about my understanding on it.

Introduction

Factory Pattern could arguably be the most widely used design pattern in Java. This type of design pattern comes under creational pattern as this pattern provides one of the best ways to create object. In Factory pattern, we create an object through a factory without exposing the creation logic to the client and refer to newly created object using a common interface.

Let’s first look at the simplist factory pattern.

Simple Factory Pattern

In my daily coding life, Simple Factory Pattern is enough to use. It suits well when we want to use a factory class to encapsulate creation logic of some product class that we would like to create. This product class can be extended by many sub-classes, which we are usually not interested in. We would rather like the factory to do its work, choose suitable sub-classes and create corresponding instances, by passing type information into the factory method.

Let’s look at a concret example.

Say we have a product class called Car, stands for cars. Different car factory can manufactory different cars, which can be considered as sub-classes of Car. So we can have BmwCar, VolvoCar, TeslaCar, and so on, demonstrated below.

Suppose we have a magic car factory called CarFactory, which is able to create multiple brands of cars. In order words, it can create BmwCar, VolvoCar and TeslaCar. When some type of Car is requested, the only thing to do is to tell the CarFactory what type of Car to create, and leave creating the car to this factory. How the car is manufactured does not concern, only that the factory will deliver the car fufilling all the requirements concerns.

As a client of this factory, how do I tell CarFactory which type of cars to create? It can be passed to createCar() method of CarFactory via method arguments.

Inside this createCar() method, the factory can choose the actual car type to create based on arguments passed in.

See complete code example at this github repo: https://github.com/gdong42/factory-pattern

What’s the benefit of this pattern? In this pattern, the caller side does not need to know the exact type implementation and its creation details, it only provides the required type name information. So this pattern reduces the complexity of the client, and decouples the creation logic of various implementation from invocation logic to some extent.

What about the cons? Let’s think about it in real world. There are few such factories. Because this magical factory needs to know how to create every product, which is almost impossible. OOP reflects the real world, therefore it is not reasonable to have a super magic factory that can create all type of products as well in the software world. In other words, each time when we want to add a new car type, we need to update createCar(). This should better be avoided.

Another problem is that SimpleCarFactory class has to depend on all car types, due to the truth that it contains all creation invocation logic in one giant factory. This leads to the client code coupling all product types,  which might never be called by the client, and thus should be optional instead of mandatory dependencies. What we expect is that when we need some kind of product, we use a factory to create it, only with required dependency that has the underlying implementation module.

How to improve this pattern to solve above problems? We will discuss this in the next installment of this topic.

 

Gan Dong

I'm a software programmer. Loving coding, music. And life.