Design Patterns provide an industry-standard approach to solving a recurring problem.
1. Creational Design Patterns
They define the way an object is created.
Factory Method: This ensures that the correct object is created according to a parameter received.
Implementation: A Factory class is created which returns different Child objects based on an input String passed to its method/constructor and using a switch case.
Eg: A car company gets the request to create a car. This request is given to the factory which decides how the car should be created based on its model.
Abstract Factory method: This ensures that the correct object is created according to a parameter when there are multiple levels of subclasses.
Implementation: When there are two levels of overriding, an abstract factory class or an interface is used to identify the first level of child class and for identifying the second level, there are separate concrete factory classes.
Eg: When a car factory handles different companies, it should first decide for which company and then decide which model to be manufactured.
Singleton: This ensures that only one object for a class is created.
Implementation: A private constructor is created and a public synchronized static getInstance() method to call it.
Eg: In an apartment, the residents decide that only one borewell should be dug for the entire community.
Prototype: This ensures that a copy of the existing object is returned when a new object is requested. This is used when an object creation is costly due to some reason (like db calls).
Implementation: A Prototype class is created which implements Cloneable and defines clone method (shallow or deep). This also has a list of predefined objects. So getInstance() method simply clones the predefined objects when called.
Eg: A Xerox machine just takes multiple copies of the same content.
Builder: This ensures that an object is created step by step.
Implementation: Instead of the actual class using its setter methods, a builder class is populated with its setters step by step. Finally this builder object is passed as a parameter to the actual class' constructor to create the actual object.
Eg: An excel/pdf report is generated after formatting it line by line.
2. Structural Design Patterns
They define the way different types of objects can have a connection.
Adapter: This ensures that a class gets some of the features from another class.
Implementation: If a class cannot use features from another class directly due to its hierarchy, another adapter class is created as a child of both the classes (implements interface of our class, extends other class) and this class' object is created for processing.
Eg: A phone charger has an adapter that converts AC to DC since phone cannot use AC directly from the socket.
Bridge: This ensures that two classes are loosely coupled.
Implementation: Since inheritance creates tight coupling, composition (has-a relationship) is used. A class has another class as its instance variable and methods to operate on that class. This helps in doing operations on both classes without affecting their hierarchies.
Eg: A switch can be used in a house to operate a fan without knowing the technical details of the fan. So switch acts as the bridge here.
Composite: This ensures that a hierarchy is defined in a tree model.
Implementation: An interface can have its implementations which in turn can have multiple child classes.
Eg: Employee hierarchy in a company. Each manager can have employees under him and managers are in turn coming under General Managers or Vice Presidents.
Decorator: This ensures that the behaviour of all sub classes can get altered without actually modifying them.
Implementation: An interface has some subclasses. Another abstract class implements this interface and adds the extra behaviour. The abstract class has a constructor parameterized with an interface object. This way the extra behaviour can be added to the interface.
Eg: Pizza and its sizes come under one hierarchy. Decorations on the Pizza can be decided from a separate Decorator class.
Facade: This ensures that multiple classes can be accessed from only one central class without knowing their internal details.
Implementation: One Facade class has instance variables of multiple classes and a constructor in which other classes are instantiated.
Example: In a restaurant only the menu card is displayed to the customers hiding the background details.
Flyweight: This ensures that a lot of objects can be created without much memory requirement.
Implementation: This combines factory and prototype design patterns. A factory has a hashmap to save objects. When a new object request comes with its type passed as String, if the key (ie, type) is already present in the hashmap, it returns that object, else it creates new object using a switch case. Flyweight resources are immutable.
Example: String pool which reuses String literals.
Proxy: This ensures that an actual class is accessed only through its proxy.
Implementation: A Proxy class is created whose constructor actually creates objects for the Real class.
Example: UPI is a proxy for a Bank account.
2. Behavioural Design Patterns
They define the way objects talk to each other.
Chain of responsibility: This ensures that different classes are called one after the other.
Implementation: Either we can call the classes in the order, or we can create objects inside constructor in the order.
Example: Supply chain of products
Iterator: This ensures that objects can be iterated through.
Implementation: An Iterator Class implements Iterator and overrides its next()/hasNext() methods. The actual class has iterator() method to create the object of the Iterator class, using which it can traverse through the lists in the Actual class.
Example: A video playlist
Mediator: This ensures that objects talk to each other only through the Mediator.
Implementation: A Mediator class has instance variables of other classes. The Mediator object is used to work on the other classes
Example: Travel Agencies work as Mediator for different air services.
Observer: This ensures that all Observers are updated when there is a change.
Implementation: A common class has instance variables of all Observer classes. It also has methods to update the Observers whenever its onchange() method is called.
Example: All travelers should be informed when there is a change in schedule.
Strategy: This ensures that different child objects can have different behaviours.
Implementation: An interface can add a behaviour to a particular class. But if it needs its implementation also, then that interface's concrete child is added as instance variable to the required child classes.
Example: An IT team may be looking for the skills Java, .Net etc. from the resources while all resources are part of the Employee hierarchy.