BNCC x GO-JEK Boot Camp (Day 9: Design Pattern)

Do you ever wonder about how big company such as GO-JEK which has more than hundreds programmers working in same code ? How does GO-JEK combine that hundreds programmer which has their own way of thinking, coding style, belief into one solid application ? The secret recipe is by implementing Design Pattern.
Design Patterns are typical solutions to commonly occurring problems in software design. They are blueprints that can be taken and customized to solve a particular design problem in your code. As per the design pattern reference book Design Patterns — Elements of Reusable Object-Oriented Software written by Erich Gamma, John Vlissides, Ralph Johnson, and Richard Helm, collectively known as the Gang of Four , there are 23 design patterns which can be classified in three categories: Creational, Structural and Behavioral patterns. But, in this article, I only tell you some of most common used design pattern in real life project especially in Go-Jek.
A. Creational Patterns
Creational design patterns are responsible for efficient object creation mechanisms, which increase the flexibility and reuse of existing code. These design patterns provide a way to create objects while hiding the creation logic, rather than instantiating objects directly using new operator.
1. Singleton
This pattern involves a single class which is responsible to create an object while making sure that only single object gets created. This class provides a way to access its only object which can be accessed directly without need to instantiate the object of the class.
The most common reason for this is to control some shared resource, for example, database. Imagine that you had created an object, and after a while, tried to create a new one. In this case, you would want to receive the old object, instead of creating a new instance. It can not be done with a regular constructor since every constructor call always returns a new object by design.

Are you still confused? Let me explain again using this simple example using .Net . Imagine you want to build application that when you create new file it will open new windows/form child.

By using that code, each times when we press the create new file button, a new object is created and the form child will be opened. If you don’t implement singleton and you press the options 5 times, the windows will open 5 times too. We can implement singleton principle to solve this problem, like this :


By applying such a pattern, the form child object will only be created when the object is first created or when the object is exposed (form is closed). When an object already exists it is no longer created. Therefore, if we click the menu 5 times, there will only be 1 form.
Checklist to do Singleton
- Define a private static attribute in the “single instance” class.
- Define a public static accessor function in the class.
- Do “lazy initialization” (creation on first use) in the accessor function.
- Define all constructors to be protected or private.
- Clients may only use the accessor function to manipulate the Singleton.
2. Builder
Builder is a creational design pattern that lets you produce different types and representations of an object using the same building process. Builder allows constructing complex objects step by step.
Imagine a complex object that requires laborious step by step initialization of many fields and nested objects. Such code is usually buried inside a constructor with lots of parameters, or worse, scattered all over the client code.

For example, let’s think how to create a House object. To build a simple house, you need to construct four walls, install a door and two windows, build a roof. But what if you want a bigger, brighter house, with a backyard and other goodies?
The simplest solution that comes to mind is to extend the base House class and to create subclasses to cover all combinations of the parameters. The obvious problem with this approach is a considerable number of subclasses you will end up with. Any new parameter, such as porch style, will require growing this hierarchy even more.
On the other hand, you can create a giant constructor in the base House class that accepts all possible parameters of resulting house. While this approach will indeed eliminate the need for sublcasses, it will also create another problem.
Some of these parameters will be unused most of the time, making constructors calls pretty ugly. For instance, most houses do not have a swimming pool. Therefore, all parameters related to swimming pools will be useless in 99% of cases.
The Builder pattern suggests to extract the object construction code out of its own class and move it to separate objects called builders.
The pattern organizes the object construction into a set of steps (such as buildWalls, buildDoor, etc.) To create an object, you will need to call several building steps in a builder class. The important part here is that you do not need to call all the steps. You can use only the steps necessary for producing a particular configuration of an object.
Often, the same construction step will be different for various products that you are trying to build. For example, a cabin may be build with wooden logs, but a castle must be build with stone.In this case, you can create several different builder classes that implement the same building steps in a different manner. Then you can use these builders in the same construction process to produce different kinds of objects.
For example, there is a StoneBuilder class that makes everything from stone and a WoodBuilder class that uses wood. You could pass one of them through a set of construction steps to produce a house built either from stone or wood. This would work only if the client code that calls building steps interacts with builders using their common interface.
You can go even further and extract the whole construction process to a special class called Director. In this case, the Director will be defining the order of building steps, and a Builder object, linked with the Director, will execute them. This structure will hide any construction details from client code.
3. Factory
Factory Method is a creational design pattern that provides an interface for creating objects in superclass, but allow subclasses to alter the type of objects that will be created.
Imagine that you are creating a logistics management application. The first version of your app can handle only transportation by trucks, so the bulk of your code lives in a Truck class. After a while, your app becomes so popular that you get tons of requests to include sea transportation as well.
Great news, right?! But how about the code? It looks that most of your code is coupled to the Truck class. Adding Ships would require making changes to the entire codebase. Moreover, if you decide to add another type of transportation to the app, you will probably need to make all of those change again. You will end up with nasty code riddled with conditionals, which select behaviors depending on classes of transport objects.
The Factory Method pattern suggests replacing direct object creation (using a new operator) with a call to a special “factory” method. The constructor call should be moved inside that method. Objects returned by factory methods are often referred to as “products.”

At first glance, such move may seem pointless. But now you can override the factory method in a subclass and change the class of an object that will be created. Let’s see how it works:

Of course, there is slight limitation: all products must have a common interface (say, Transport). Factory method in a base class should be returning this common interface.

Subclasses may return different concrete products as long as these products have a common base class or interface (for example, both Truck and Ship implement the Transportinterface).
B. Structural Patterns
Structural design patterns are responsible for building simple and efficient class hierarchies and relations between different classes.
1. Composite
Structural design patterns are responsible for building simple and efficient class hierarchies and relations between different classes. you have two objects: Product and Box. The Box can contain several Products and a number of smaller Boxes inside. These little Boxes can also hold inside some Products or even smaller Boxes and so on.
Now, imagine that your Products and Boxes can be a part of order. How hard can it be to calculate the order total?
The Composite pattern suggests treating all different Products and Boxes through a common interface that has a method getPrice().

In Products, it will just return the product's price. But Boxes will get much more interesting behavior. A Box will go over its content and ask every item its price. Naturally, if an item was a product, it will return the price right away. But if that was a smaller box, it will also start looking over its items asking for the price until it can return the total. Once the subtotal is calculated, a Box can even add some extra to the full price, like a packaging cost.
Now, probably the greatest benefit of this approach is that you do not need to care much about the concrete objects that make a tree. Whether it is a single Product or sophisticated Box, you treat it through a generic interface. And the structure handles passing the requests down by itself
2. Adapter
Adapter pattern works as a bridge between two incompatible interfaces. This pattern involves a single class which is responsible to join functionalities of independent or incompatible interfaces. A real life example could be a case of card reader which acts as an adapter between memory card and a laptop. You plugin the memory card into card reader and card reader into the laptop so that memory card can be read via laptop.
Let’s see how Adapter can convert one interface into another with some basic data conversion. The example is based on the conflict between round holes and square pegs. Round holes work great with round pegs; you can determine whether or not one fits another just by comparing their radiuses. But square pegs do not have the radius measurement at all.

3. Decorator
Decorator pattern allows a user to add new functionality to an existing object without altering its structure. This type of design pattern comes under structural pattern as this pattern acts as a wrapper to existing class. This pattern creates a decorator class which wraps the original class and provides additional functionality keeping class methods signature intact.
Wearing clothes is an example of using decorators. When you are cold, you wrap yourself with a sweater. If it is still cold, you can wear a jacket on top. If it is raining, you can put on a raincoat. All of these garments “extend” your basic behavior, but are not part of you. Therefore you can easily take them off whenever you do not need them anymore.

The decorator pattern relies on special objects called decorators (or wrappers). They have the same interface as an object that they suppose to wrap, so the client code will not notice when you hand it a wrapper instead of the original object. All wrappers have a field for storing an instance of an original object. Most wrappers initialize that field with an object passed into their constructor.
So how do they dynamically change the behavior? As I mentioned, wrappers have the same interface as the target objects. When you call a decorator’s method, it executes the same method in a wrapped object and then adds something to the result. It can also be called before the original method, but that is up to the business logic.
4. Proxy
Proxy is a structural design pattern that lets you provide a substitute or placeholder for another object to control access to it. A check is a document that orders a bank to pay a specific amount of money from a person’s account to the person in whose name the cheque has been issued. Both check and cash have a common interface: they can be used as payment. Thus, a check is a proxy for a bunch of cash.
Another example, you have a powerful object that loves to consume vast amounts of system resources. You need it from time to time, but not always. Thus, the object could probably be created not at the program start, but rather when it is actually needed. Each client of this object would need to have some sort of deferred initialization code. Obviously, it leads to a lot of duplication. In an ideal world, we would put this code directly into the object’s class, but that is not always possible. For instance, the class may reside in a closed 3rd-party library.

The Proxy pattern suggests creating a substitute class that has the same interface as an original service object. Upon receiving the request from a client, the proxy object creates an instance of a service object and delegate it all real work.
But what is the benefit? You could put some code into a proxy object that would be executed just before (or after) calling the same method in a real service object. And thanks to the same interface that proxy shares with the service object, it could be passed to any code that accepts service objects.
C. Behavioral Patterns
Behavioral patterns are responsible for the efficient and safe distribution of behaviors among the program’s objects.
1. Template
In Template pattern, an abstract class exposes defined way(s)/template(s) to execute its methods. Its subclasses can override the method implementation as per need but the invocation is to be in the same way as defined by an abstract class (without changing its structure).
Imagine that you are writing an application for data mining office documents. Users would feed it documents in various formats (PDF, DOC, CSV) and receive useful uniform data instead. The first version of the app could work only with DOC files. The following edition received the CSV support. A month later, you had added the ability to extract data from PDF files.
At some point, you noticed that all three parsing algorithms have a lot of similar code. While they were quite different in dealing with file formats, the data extraction and analysis had been almost identical for all formats. Hence, it would be nice to get rid of the code duplication, leaving the algorithm structure intact.
There was another problem related to client code that used these algorithms. It had lots of conditional that were picking a proper course of action depending on the selected algorithms. If all three parsing classes were sharing a common interface or a base class, these conditional could be eliminated in favor of using polymorphism.
The Template Method pattern suggests to break down an algorithm into a series of steps, turn steps into methods and call them one by one inside a single “template” method. Subclasses will be able to override particular steps, but not the actual template method, leaving the algorithm structure unchanged.

In our data mining app, we could create a common base class for all three parsing algorithms. The crucial part of the class would be a template method that looks as this:
method templateMethod() is
openDocument();
extractRawData();
parseRawData();
analyzeData();
closeDocument();
At first, you can declare the template method steps as abstract, making all steps mandatory to override and forcing subclasses to provide their own implementations. But then, once all methods are in place, you can start scanning subclasses for similar code and pulling it into the base class, making these steps optional to override.
In our case, the steps of opening and closing documents will be different for all three file types, so there is no point in touching them. But other steps, such as parsing and analysis, can be pulled into the base class, allowing subclasses to share the common code.
Source:
https://www.tutorialspoint.com/design_pattern
https://refactoring.guru/design-patterns
https://agung-setiawan.com/berkenalan-dengan-singleton-pattern/
https://agung-setiawan.com/implementasi-nyata-singleton-pattern/
