Why you should learn design patterns?
In many interviews you might have encountered a lot of questions about interfaces, abstract classes, delegates and other features related to object-oriented programming along with the design patterns related questions.
Once you understand the design patterns it makes you very comfortable in attending any interviews as well as it helps you in applying these features in your projects or applications.
We should note the point that implementing design patterns in applications are proven and tested.
To make your applications to be scalable, reliable and easily maintainable you should Write the code aligning with design patterns.
Now let's understand what design patterns are
What are design patterns?
Design patterns are evolved as reusable solutions to the problems that we encounter every day of programming.
Design patterns main target is to solve object generation and integration problems.
In other words, design patterns act as templates which can be applied to the real-world programming problems.
History and evolution of design patterns
Concepts of design patterns brought by Gang of Four who are the four authors of the book elements of reusable object-oriented software.
Gang of Four has divided the book into two parts:
First part explaining about the pros and cons of object-oriented programming.
Second part is about the 23 classic software design patterns evolution.
From then, Gang of Four design patterns have made a significant role in the software development lifecycle.
Types of design patterns
Gang of Four have created the design patterns into three types based on different problems encountered in the real-time applications.
- Creational Patterns
- Structural Patterns
- Behavioral Patterns
These patterns outline a number of ways in which objects could be created and their lifecycles managed
creational pattern gives the program more flexibility in deciding which objects need to be created for a given case
The patterns are as follows:
Abstract Factory pattern
Factory Method pattern
what exactly is the abstract factory pattern?
It is like a factory but everything is encapsulated
- The method that orders the object
- The factories that build the object
- The final objects
- The final objects contain objects that use the strategy pattern.
The strategy pattern just uses what is called composition or in other words its class fields are actually objects themselves.
What can you do with an abstract Factory?
It allows you to create families related objects without specifying a concrete class which is extremely important because it provides you in ton of flexibility.
You want to use them whenever you want to have many objects that can be added or changed dynamically during runtime.
With an abstract Factory you can model anything you can imagine and have those objects easily interact with numerous other objects through common interfaces.
The only bad thing about an abstract Factory is it can get very complicated.
What is the Builder pattern?
Builder pattern is a pattern that's used to create objects made from a bunch of other objects.
When you want the creation of these parts to be independent of the main object.
Also, to hide the creation of the parts from the client so both are not dependent upon each other.
Whenever you create a builder pattern the Builder part of the Builder pattern knows all the specifics and every other class involved knows nothing about what's going on in regards to the specifics of the final object you're going to create.
What is the factory method pattern?
Basically, by definition you would use the factory pattern whenever you would want a method to return one of several possible classes that share a common superclass.
So, let's say I wanted to shoot a enemy onto the screen at random.
Well if everything is hard-coded and I don't know what type of enemy that's going to go onto the screen using basic programming techniques that makes it very hard.
However, let's say that I create a random number generator and each potential enemy class is a designed one of the numbers that could pop out of that random number generator.
I could then send that number to the factory object and it will return for me a dynamically created enemy and throw it on the screen.
So, it's very important the MOL main concept here is we want the capability to have classes chosen at runtime and that's what the factory pattern provides for us.
When would you use the factory method pattern?
When you don't know ahead of time what class objects you might need.
However, there's a caveat to that make sure that all the potential classes are of the same subclass hierarchy which means somewhere up the list they all have the same superclass.
You would also use a factory pattern to centralize class selection code.
When you don't want the user to have to know every single potential subclass.
And of course, like all ways to encapsulate object creation which is always great.
What is a singleton pattern?
It is used when you want to eliminate the option of instantiating more than one object. You're going to create a class and it is only ever going to be able to create one object from that class.
Now you might ask yourself well when would I actually want to use something like that? Actually, a lot of times.
It may have demonstrated using a class that's going to hold all of the potential Scrabble letters and Scrabble is a pretty common board game so I thought you would make a lot of sense here using this.
it's going to hold all these potential Scrabble letters so that all the users that want to use this object can access those letters however it's also going to spit out new ones upon request to all the different users.
Now why the singleton pattern makes this great is each player will share the same potential letter list however each player is going to have their own set of letters to create words from.
So, the singleton pattern makes a lot of sense in this situation.
What is the prototype pattern?
It is when you want to create new objects or instances by cloning or copying other objects or instances in a nutshell that's the prototype pattern.
So what does it allow you to do it allows for the adding of any subclass instance of a known superclass at runtime.
You would want to use the prototype pattern when there are numerous potential classes that you want to only use if needed at runtime.
One of the benefits of the prototype pattern it reduces the need for creating multiple subclasses.
These patterns describe a variety of different ways to add functionality to existing objects
In simple words this pattern focuses on decoupling interface implementation of classes and its objects
The patterns are as follows:
- Adapter pattern
- Bridge pattern
- Composite pattern
- Decorator pattern
- Façade pattern
- Flyweight pattern
- Proxy pattern
We're going to talk about an easy design pattern to understand it is called the adapter design pattern now
What the adapter design pattern allows you to do?
The adapter design pattern allows you to use two completely incompatible interfaces and get them to work together just like any other adapter.
Let's say you only have two plugs in a wall outlet however you want to connect something that has three plugs what are you going to use an adapter which is exactly what this guy is.
You're going to use the adapter pattern whenever the client expects to use a target interface which means the target interface in this situation would be a two pronged plug however you have a three prong plug and that's what the adapter is going to do it's going to convert the three prong into the two prong.
The adapter class is going to allow you to use any available interface that makes sense of course with the target interface.
And to look at it in a completely different way any class can work together as long as the adapter solves the issue that all classes must implement every method defined by a shared interface.
What is the bridge design pattern?
The official definition is to decouple an abstraction from its implementation so the two can vary independently.
The pattern is used to separate an abstraction from its implementation so that both can be modified independently.
This pattern involves an interface which acts as a bridge between the abstraction class and implementer classes.
With bridge design pattern both type of classes can be modified without affecting each other.
The implementation guidelines of the bridge design pattern
We need to choose bridge design pattern when we want to avoid a permanent binding between an abstraction and its implementation.
Both the abstraction and their implementation should be extensible by sub classing. When the changes in the implementation of an abstraction should have no impact on their clients that is their code should not have to be recompiled.
We choose this pattern when we want to share an implementation among multiple objects. Last but not the least we want to hide the implementation of an abstraction completely from clients.
The composite design pattern is another one of those two patterns it sounds really complicated whenever you read the definition of it but once you see the code and you see it in pictures it makes a hundred percent sense.
It allows you to treat individual objects and compositions of objects uniformly that is the typical definition for the composite design pattern.
They allow you to represent part whole hierarchies what a part whole hierarchy is simply is it’s when components can further be divided into smaller and smaller components.
A more logical definition is the composite design pattern allows you to structure data or represent the interworking of every part of a whole object individually.
What is Decorator design pattern?
Attach additional responsibilities to an object dynamically decorator provides a flexible alternative to sub classing for extending the functionality.
This pattern falls under the category of structural design pattern and is also known as wrapper pattern which means decorator design pattern solves the problem of adding additional functionality to already existing object without altering its existing structure.
A point to note that this pattern aligns with solid design principles.
Also, this pattern creates a decorator class which wraps the original class and adds new behaviors or operations to an object during runtime.
Implementation guidelines of decorator design pattern
We need to choose this pattern then you need to add responsibilities to individual objects dynamically and transparently that is without affecting other objects.
For example, changing legacy code can be a tough thing to achieve in those circumstances it is easier to modify existing code with decorators.
We need to choose this pattern when the extension by sub classing is impractical which means sometimes a large number of independent extensions are available and are possible and would result in an enormous sub classing which are not desirable to support every combination.
We need to choose this design pattern when a class definition may be hidden or otherwise unavailable first sub classing.
For example, using this pattern we have a flexibility to change classes despite there being sealed I'm sure that you understand that inheriting subclasses is not possible in those situations decorate a design pattern comes handy so that we can modify the existing class structure using a decorator.
What is facade design pattern?
Provide a unified interface to a set of interfaces in a subsystem.
Facade defines a higher-level interface that make the subsystems easier to use.
The term facade is derived from French facade which means frontage or face.
If facade is generally referred to the exterior appearance of the things and it could be a building or any other form of representation.
Now to elaborate this we can say that facade design pattern provides abstracted view of subsystems by hiding its complexity.
It wraps the complex subsystems with a simple interface.
This interface is responsible for calling functions of existing subsystems.
Implementation guidelines of facade design pattern
We need to use the façade pattern when we want to provide a simple interface to a complex subsystem. subsystems often get more complex as they evolve.
Most patterns when we apply them result in more and more smaller classes this makes the subsystem more usable and easier to customize but it also becomes harder to use for clients that don't need to customize.
A facade can provide a simple default view of the subsystem that is good enough for most lines.
Also, we need to use this pattern when there are many dependencies between clients and the implementation classes of an abstraction.
In this scenario we introduce a façade to decouple the subsystem from clients and other subsystems thereby promoting subsystem independence and portability.
We do need to use this design pattern when we want to layer the subsystems and use a facade to define an entry point to each of this subsystem level.
To this point if the subsystems are dependent then you can simplify the dependencies between them by making them communicate with each other solely through their facades.
What is the flyweight design pattern?
It's used whenever you need to create a large number of very similar objects when I say large I mean like a hundred thousand instead of five thousand or whatever you're used to.
You use the flyweight design pattern to reduce memory usage by sharing objects that are similar in some way rather than always creating new ones.
We're going to talk about an extremely simple design pattern and that is known as the proxy design pattern.
What is the proxy design pattern?
The proxy is a class which is going to be used to limit access to another class.
You may do this for security reasons because an object is intensive to create, or that object is in a remote location that you'd like to have a proxy or a thing that sort of decides what methods are available what fields are available from that outside object.
These patterns describe how objects interact with each other
The patterns are as follows:
- Chain of responsibility pattern
- Command pattern
- Interpreter pattern
- Iterator pattern
- Mediator pattern
- Memento pattern
- Observer pattern
- State pattern
- Strategy pattern
- Template method pattern
- Visitor pattern
What exactly is the chain of responsibility design pattern?
This pattern has a group of objects that are expected to between them be able to solve a problem and if the first object can't solve it, it just simply passes the data to the next object in the chain.
Avoid coupling the Sender of the request to its receiver by giving more than one receiver object a chance to handle the request. chain the receiving objects and pass the request long the chain until and object handles it.
The chain of responsibility pattern creates a chain of receiver objects for a request.
In this pattern, normally each receiver contains reference to another receiver.
if one receiver cannot handle the request then it passes the same request to the next year receiver and so on.
One receiver in the chain handles a request, or one or more receivers in the chain handles a request.
what is the command design pattern?
The basic definition is the command design pattern is a behavioral design pattern in which an object is used to represent and encapsulate all the information needed to call a method at a later time.
This information includes the method name, the object that owns the method and the values for the method parameters.
Now if that didn't make any sense let's move on and explain a completely different way
Basically, what it allows you to do is store lists of codes that is executed at a later time or many times and on top of that normally with the command design pattern there's a capability for you to undo commands.
What happens is the client or the application part of your program says I want a specific command or a list of code to be executed whenever a method called execute () is called on one of these encapsulated (hidden) objects.
Then an object called the invoker whenever it is invoked to perform a command to set it in motion transfers this command to another object that is called the receiver and the receiver has the actual code that you want to execute and whenever it gets the command from the invoker to execute it, it executes it.
Basically, if we have this object called “TurnTVOn” this is actually a command this command is defined then “DeviceButton” which is another class or object that's going to be created whenever it is called it sends “TurnTVOn” of course there's going to be interfaces between all this we can use polymorphism so whenever “TurnTVOn” is called that method then will be executed by the receiver or television another.
what is the interpreter design pattern?
As I was first taught about this pattern the professor said this exact line I wrote it down in a notebook the interpreter pattern is normally ignored and I've seen many places online this pattern is almost never used.
what exactly is the iterator design pattern?
The iterator design pattern is going to provide you with a uniform way to access different types of collections of objects.
For example, if you get an Array, ArrayList and a HashTable that are all full of the same type of objects you could pop out an iterator for each and treat them the same.
What this does for you is provides a uniform way to cycle through all of these different types of collections.
On top of that you're also going to be able to write Polymorphic code because you can refer to each collection of objects in the same way because they are going to implement the same.
What is the mediator design pattern?
It is used to handle communication between related objects that are referred to as (colleagues).
all communication is handled by the mediator and the colleagues do not need to know anything about each other.
The gang of force definition is that this mediator design pattern allows loose coupling by encapsulating the way disparate sets of objects interact and communicate with each other and the mediator design pattern allows for the actions of each object to vary independently of one another.
What is the memento design pattern?
It's a way to store previous states of an object quite easily.
First you have the memento which is going to be the object that is going to be stored in multiple different States and by different states I just mean the fields are going to have different values and so forth and so on.
Then you're going to have the originator it is going to Set and Get values from the currently targeted memento object and it's also going to create new mementos and assign current values to them.
Then finally you have the caretaker it holds an ArrayList in my situation anyway that's going to contain all previous versions of the memento objects and it's going to be able to both store as well as retrieve stored mementos that are stored in the ArrayList.
When do you use the observer pattern?
When you need many other objects to receive an update when another object changes.
For example, let's say we have a subject or publisher object that is going to represent thousands of individual stocks in the stock market if you would need to send updates to multiple observers or subscribers you would use the observer pattern to do that.
What is the benefit of the observer pattern?
You get the benefits of loose coupling. the subject or publisher doesn't need to know anything about the observers or subscribers I'm referring to them as two different things because I think publisher makes more sense but basic jargon OLP concepts says that we should use subject and observers.
the only negative of the observer pattern is the subject or publisher may send updates that don't matter to observers that are subscribed.
What is the state design pattern?
It allows objects to alter its behavior when its internal state changes and in doing so the object will appear to change its class.
This one's all about composition and you're going to have three main parts:
First, you're going to have what is called the “context” or the “account” what it's going to do is maintain an instance of a ConcreteState subclass that is going to define the current state
Then you're going to have the “state” which defines an interface for encapsulating the behavior associated with a particular state of the context.
And then you have the concrete state each subclass is going to implement a behavior associated with a state of the context.
When to use the strategy pattern?
You are going to use the strategy pattern when you want to define a class that will have one behavior that is similar to all the other behaviors in a list.
So, we have animals that fly and animals that don't fly the similarity is that flying is involved whether it is they can't fly or they can fly.
To explain it another way you want a class object to be able to choose from:
- Not flying
- Fly with wings
- Fly super-fast
By adding in the strategy pattern you're going to be able to dynamically create whole new different types of flying typed animals.
So, to get right down to it you're going to use the strategy pattern when you need to use one of several behaviors dynamically.
Other good reasons to use the strategy pattern
It often reduces long lists of conditionals so if you start seeing that using many many different types of conditionals chances are strategy patterns going to help you out.
Of course, it avoids duplicate code.
It keeps class change from forcing other class changes.
It also allows you to hide complicated or secret code from the user.
There is only one negative you're going to have an increased number of objects and classes if you use the strategy pattern.
Is a extremely easy design pattern to understand
What is the template method design pattern?
It's used to create a group of subclasses that have to execute a similar group of methods.
To implement it you create an abstract class that's going to contain a method called the template method.
You create the abstract class it's going to contain a method called the template method and the template method contains a series of method calls that every subclass object will call.
However, in certain situations the subclass objects that are formed from this guy they're going to be over to override some of the method calls that don't work for it.
What is the visitor design pattern?
It allows you to add methods to classes of different types -however they don't have to be different types- but that's just an added level of complexity without much altering to those classes.
This allows you to make completely different methods depending upon the class that is used.
To phrase it another way it allows you to define external classes that can extend other classes without majorly editing them.
Note that it's very important to have basic knowledge about the object-oriented concepts like: abstraction, inheritance, polymorphism, encapsulation, interfaces, classes and abstract classes to understand design patterns better.