Design Pattern 101: Singleton and Factory Pattern
Design Pattern
If you are a Software Engineer, I’m 99% sure that you have heard about it before, but knowing about it is one different thing. Do you really understand what Design Pattern really is?
Relax!
Design pattern is not a rocket science, it doesn’t need rocket scientist to figure it out. As advance as the word “Design pattern” sounds, it isn’t really all that complicated. You don’t really need to be good in order to learn and understand it, but to be a good Software Engineer you need to learn it.
What exactly is Design Pattern?
In nutshell, design pattern is a solution. What solution do you ask? It is a solution that is crafted and designed by brilliant minds in order to solve repeating problem that often occurs in Software development process.
Design pattern mostly designed in order to tackle OOP issue as design pattern often interacts with classes, objects and OOP-concept such as Inheritance and Interface.
It still sounds pretty abstract for me…
Yes, i understand, without real example there is no doubt that design pattern will still sound like something that can make a rocket for you out of nothing. There are tonnes of design pattern techniques and I will cover two of the most used design pattern today, the so called Singleton Pattern and Factory Pattern.
Singleton Pattern
It is without doubt the most popular design pattern and the easiest one to grasp.
Let’s assume that you are a rich enough and you have your own.. lets say Car Shop, but you can only afford one for now because you are not as rich as Bill Gates yet. You still love coding and you try to simulate your shop programmatically!
So first you make a Car Model
Car.javapublic class Car(){
//default empty constructor
public Car(){} public void start(){
System.out.println("Car engine start");
}
}
Looks good, now you make your Car Shop class
CarShop.javapublic class CarShop(){
//because we want to keep track on the number of cars that we have sold
int carSold;//we start our bussiness from zero
public CarShop(){
carSold = 0;
}//function to sell our car, as it returns car
public Car sellCar(){
carSold++;
return new Car();
}
}
Great! now we want to start selling our car, assume there are several classes that want to access the car shop, what do you do?
//you do this for every classes that wants to get car
CarShop carShop = new CarShop();
Car car = carShop.sellCar();
Now, you are making car shop each time and it violates the stated rule where you can only afford one, because basically you are making a new shop everywhere.
How do you tackle it? You use Singleton pattern of course:
CarShop.javapublic class CarShop(){
private static CarShop carShop;
private int carSold;//see that we make the constructor private
private CarShop(){
carSold = 0;
}//you make a static function that return the carShop
public static CarShop getInstance(){
if(carShop == null)
carShop = new CarShop();return carShop;
}//function to sell our car, as it returns car
public Car sellCar(){
carSold++;
return new Car();
}
}
As you might realized it, the constructor for CarShop is private so that no one can instantiate Car Shop anymore and we are providing a single access to CarShop object, through the function getInstance. Now, we simply call this in our class:
Car car = CarShop.getInstance().sellCar();
MAGIC!
Nah, it is not magic is just the way of manipulating static function and private constructor.
Factory Pattern
Continue on from before, let’s say there are different kind of cars: Sport car, Family Car or even Flying Car! And you are selling those different kind of cars in your shop, so you make more classes and modify your function.
//more Car classes
SportCar.javapublic SportCar()
{
public SportCar(){}public start(){
System.out.println("Sport car engine start!")
}
}FlyingCar.javapublic FlyingCar()
{
public FlyingCar(){}public start(){
System.out.println("Flying car engine start!")
}
}...
//and etc
//And now your sell car function
public SportCar sellSportCar()
{
carSold++;
return new SportCar();
}... make more functions for each car and so on..
Looks good but like usual, it is not good enough. Why? There are several points on that:
- The CarShop doesn’t need to know how the car is made, it only needs the car, in summary car shop is not supposed to instantiate the Car object.
- We need to keep on creating new function for each new car that will be sold in the shop.
- Our Car object model become unused.
Of course, as we are studying design pattern, we are going to use Factory Pattern on that! We are going to modify the model beforehand and we are going to make our Car class to become Interface.
Car.javapublic interface Car{
void start();
}..onto our other classesSportCar.javapublic class SportCar implements Car{
public SportCar(){};public void start(){
System.out.println("Sport Car started");
}
}FlyingCar.javapublic class FlyingCar implements Car{
public FlyingCar(){};public void start(){
System.out.println("Flying Car started");
}
}.. and so on
Now onto the second step, we make our factory class that:
CarFactory.javapublic class CarFactory {
public Car getCar(String carType){ if(carType.equalsIgnoreCase("SportCar")){
return new SportCar();
} else if(carType.equalsIgnoreCase("FamilyCar")){
return new FamilyCar();
} else if(carType.equalsIgnoreCase("FlyingCar")){
return new FlyingCar();
}
return null;
}
}
Final step, we simply modify our CarShop class again
CarShop.javapublic class CarShop{
...
//we need to make car factory now
public carFactory;..public CarShop()
{
...
//we need to initialize our car factory before hand
CarFactory = new CarFactory();
}....
//now our functions also return car
public Car sellCar(String carType)
{
carSold++;//short and simple, our factory now provides abstraction to our shop
return carFactory.makeCar(carType);
}}..
// when we call our car shop now it will looks like this
Car sportCar = carShop.sellCar("SportCar");
Car flyingCar = carShop.sellCar("FlyingCar");sportCar.start(); //Sport car started
flyingCar.start(); //Flying car started
Using factory pattern we finally solved our issues such as:
- Our shop now doesn’t know how the car is built.
- Adding new car simply need to add more logical path inside our factory.
- Our car interface is used for everytime a new car type is out.
Wrapping up
Now, that concludes the lesson today on Singleton and Factory Pattern.
As the title stated “101”, this is just the very basic of design pattern. There are still more design patterns such as Facade, Builder, Dependency Injection, Adapter and many yet i still have to explore myself.
Technology keep on changing but design pattern never changed. Learning it will undoubtedly make you a better software engineer.
I hope you enjoy reading my article!
And if you do, please do smash the clap button and share it to your friends. Thanks for reading my article till the end.