Uploaded by AYUSHI GANG

Week 8 SE

advertisement
Week 8
Now that you have started developing or writing code for your system, it is
once again important to take the big picture view in order to make sure that
everything is going along as intended. This is software architecture.
Software architecture is a way of organizing your code. How should
different classes or modules be organized? It is actually similar to building
the architecture of any product, so there is an efficient way in which an
entire building or a house is constructed. There is efficiency of space,
efficiency of functionality, and so on. Software architecture is quite similar. It
defines the software elements or modules, the relations among them and
the properties of both the modules and the relations. Now this might all
sound very abstract. Let us take an example of two software systems:
Google search engine and another, which is a compiler. If we consider
these as software systems, what are some key differences between these
two systems? So what is the difference between a Google Search and
engine type of software system and a compiler Software System right?
So let's look at Google search, so Google search is essentially a
web-based system. So when I, as a user, type a search query, a request
goes to one of the servers of Google and Google returns a response which
returns Pages related to my query, and these types of systems are
commonly known as client server systems where data transactions
happen. In response to requests - and you might know that this is put on
predominantly how the internet functions today right, so this client server
system is a type of software architecture where there are systems which
behave as clients and other systems which behave as servers. Now, let's
look at a compiler right, so what does a compiler do? Compiler takes
source code as input and then transforms it into what is known as
assembly code and then again transforms this into an executable file which
can be run by the underlying operating system. This type of software
system is known as a pipe and filter type of system where data is passed
from one component to the other component and it is transformed and
filtered along the way. So if you have noticed this client server type of
system, which is like a Google search engine, is different from a compiler
system which is a pipe and filter type of system. So the interactions which
the different components have with each other are different. So in a
client-server model the client and server communicate with each other
through requests and response, whereas in a pipe and filter type of system,
data is passed from one component to the other. So these types of patterns
of information between different components - they are known as software
architecture styles. So let's look at some more examples to highlight this
concept.
Another type of software architecture is known as the model view controller
or the MVC type of architecture. So in this style, the views of the data are
separated from the manipulations of the data. So let's look at this MVC
architecture.
So m stands for model, which is usually the component Which models the
data required for the service. So, for example, in the case of the Amazon
Seller portal, the model is nothing but the classes or the objects which
model the tables in the database. Now the view component is nothing but
the GUI objects, the presentation, layer or the visual representation of the
model. For example, how information is seen on a particular website, so
the view component, it retrieves data from the model and displays it to the
user, and it also passes requests back and forth between the user and the
model. Now, the controller component coordinates multiple views on the
screen and helps users manipulate the model. So, for example, you can
have a filter for catalog items which is based on name in the case of the
Amazon Seller portal right. So, in this case, the controller sends this
message to the model which receives the user input and sends the
appropriate messages to its underlying views.
Another type of software architecture is known as peer-to-peer or P2P, so
P2P architecture is nothing but a distributed application with different
systems. They form nodes and they share resources with each other. So,
unlike a client server model or the MVC type of architecture, there does not
exist a centralized system which monitors all the transactions of the system
so nodes in the network. They make a portion of their resources, such as
processing power, the disk storage directly available to all the other nodes
in the network, without the need for Central coordination by servers or
stable hosts. Now let us examine the common aspects in the different
architectural styles that we saw earlier.
What is similar, one important aspect of these tiles is the notion of a
component A software is divided into components. Component is nothing
but some well defined functionality or behavior, separate from other
functionality and behavior, for example, in a client server system, the client
software is a component and the server software is another component.
Your browser, which sends a request to a search engine, is a component
and the server which responds to the request is a component.
Now that we have seen what components are, another important unit of the
architecture is connectors, components cannot function in isolation, they
have to be able to talk to each other. These are the connectors, so
characters are code that transmit information between the components
they are responsible for. Regulating the interaction among the components,
now there needs to be a standard way in which components can interact
with each other. These are called protocols. A protocol is nothing but a set
of predefined rules which describe how the component should interact with
each other. For example, it may be that, let us say there are, there is the
client component and the server component. Now both the client
component and the server component need to understand and agree upon
the way in which the message will be transmitted between them right. It
cannot be that the client sends the message you know in one format, while
the server is attempting to process the same message in a different format,
so the protocol or connector is the understanding between these two
components. The most common types of connectors are function calls and
rest API calls. You have specific rules to create endpoints which help you
communicate with other components. So how do we come up with the
components of a software system in the past, experienced designers,
consciously reused, solutions that have worked in the past? So there would
be libraries of various modules and many of these Solutions later became
standardized and are commonly known as design patterns. So there are
several good books on design patterns. For example, there is one element
of reusable object oriented software. Then there are design patterns and so
on.
The key idea is a design pattern is a description of communicating objects
and classes that are customized to solve a general design problem, so we
will be looking at some design patterns. Even if we have knowledge of
good design patterns, often even with good intentions, one might not use a
pattern correctly or new code might get added along the way. This is
actually known as an anti-pattern, so this can actually lead to a lot of
problems in the code.
So now what are warning signs that you may be headed towards an
anti-pattern? Interestingly enough, this is called a design smell, so a key
way to avoid such design smells is to follow effective guidelines of software
architecture. This is known as the solid guidelines okay, which we will
discuss. Solid, is basically an acronym. Ok, s stands for single
responsibility, o stands for open closed and so on. So we will see all these
details as we go along. So when you see that there are design smells in
your architecture, moving back towards a good design process is known as
refactoring refactoring, a design involves moving code between classes,
creating new classes and modules or removing classes that are not
required.
Solid principles are object oriented principles for Effective software design,
so these principles were conceptualized by Robert Martin, popularly known
as Uncle Bob, and he is a very prominent figure in software engineering.
He is one of the founders of the agile Manifesto of the Agile development
process and using these principles we can make our code easy to
understand and modular, and these principles support the concepts of good
cohesion and loose coupling as well.
So, let's look at these principles in detail now solid is an acronym. S stands
for the single responsibility principle. O stands for open, close principle. L
stands for liskov substitution principle. I stands for interface, segregation
and D for dependency inversion. Now, let's look at each of these principles
in detail now.
The first principle is the single responsibility principle. Now, as the name
suggests, every class should have a single responsibility or purpose right,
so every class in your Software System should have only one responsibility
in the software system. So let's take an example from the seller portal itself.
Let's have a look at this class diagram, which contains only a single class,
so the seller class contains information about the seller, the seller ID the
name, the address and about the product, and it has functionalities related
to adding a seller, deleting a seller, adding products, as well as deleting
some items from the inventory, adding items to the inventory and viewing
an inventory. So, as you would have noticed this design, it violates the
single responsibility principle right. The reason being you have functions
and attributes related to the seller related to the product and related to the
inventory right.
So, let's see how we can refactor this code, so refactoring means how can
we change this code so that it follows the single responsibility principle, so
what we can do is split that big seller class into three different classes right.
The seller class contains details only about the seller, and appropriate
functionalities related only to the seller like add seller and delete seller.
Then we have a product class which has details regarding the product and
the inventory class takes the seller ID as an attribute and different products
get added to the seller inventory. So in this way each class has a single
responsibility or purpose.
Now that we have seen the single responsibility principle, let's look at the
next principle, which is the open, close principle. So, according to the open,
close principles, software entities should be open for extension, but it
should be closed for modification. So what does this mean? This means
that whenever we write code, we should make sure that we are only
extending a class's behavior, for example, by creating subclasses Etc
without modifying the existing glasses.
So, let's take an example, so let's say we have a product class right which
has product attributes like the ID name type and cause. Now, let's say I
want to add a new product type, for example: clothing. So a clothing
product, like a shirt, will have additional parameters like the size, the color,
Etc. Right now, one way to add a new product type like clothing is to make
changes in the existing product class right. So I can add size and color
attributes and I can add a new member function called add product which
takes the size and color as well. Now this design actually violates the open,
close principle. So in this case, we are modifying the product class by
adding attributes to an existing class.
So now, let's see how we can implement the open, close principle for this
design right. So what we can do is create another class called clothing
which inherits properties of the product plus, so clothing is a subclass of
product, and attributes specific to the clothing class can be defined in the
clothing class, so the clothing class inherits these attributes Like product ID
name, type cost as well as it has specialized attributes like size and color.
So in this way we see that our product class is untouched, but we are
extending the class by adding a new class called clothing. In this way, our
design satisfies the open - closed principle.
Now that we have seen what the open close principle is, let's look at the
next principle, which is the Liskov substitution principle. So the liskov
substitution principle generally works and is applied to inheritance
hierarchies where you have a base class and you have derived classes
which extend the functionality of the base class. Now the liskov substitution
principle states that the derived classes should be substitutable by their
Base Class. So what this means is that, let's say we have a derived class D
and D is a subtype of a base class, let's say B, and what liskov substitution
principle says is that we should be able to replace methods in the base
class with the methods In the derived class, without interrupting the
behavior of the program, so this might seem a little abstract.
So, let's take an example, so let's say we want to implement a feature
where we want to notify sellers about feedback regarding their product and
we want to notify sellers through email. So here is one possible design
which implements this feature, so we have a product class and we have an
abstract class known as feedback notification, which has an abstract
method called notify right and the email notification class, extends the
feedback notification class and the notify method here actually implements
the feature of notifying sellers about the feedback through email.
Now, let's say I want to extend this feature, and now I want to notify sellers
through email as well as SMS. So what we can do is create another class
known as SMS notification, which extends feedback notification right and
we can implement the logic of how sellers will be notified through SMS in
the notify method. However, there is a slight issue here right, so if you've
noticed the third parameter is email and here instead of email, we need to
have a mobile number field right, since we are going to send an SMS to a
particular mobile number and not an email. So here this design is actually
violating the liskov substitution principle, because the method in the base
class cannot be substituted by this method in the derived class right.
What changes should we do in this design so that we can follow the liskov
substitution principle, so what we can do, as we notice that this email field
was causing issues right, so we can remove that field from the abstract
class and we can create derived Classes and add the necessary
parameters there. So, for example, we'll have an email notification class
which has an additional parameter: email, we'll have an SMS notification
class which will have an additional parameter: Mobile number. Both of
these classes extend the feedback notification class and, if you look at the
method, both can actually implement the abstract method from the base
class. So in this case, you can see that the methods in the derived class
can be substituted by the methods in the base class. In this case, and so
this design follows the liskov substitution principle.
We are going to look at I, which is the interface segregation principle.
So first, what is an interface right? So an interface is nothing but a group of
related methods right with empty bodies. So we do not write the definition
of what these methods do. We just specify what the interface should do,
what the methods are, but not how we are going to implement these
methods. Other classes can implement this interface by implementing all
the methods in that interface.
So what is the interface segregation principle state? It states that we should
not force any client to implement an interface which is irrelevant to them.
So what does this mean? This means that if we have an interface, we
should make sure that all the methods in that interface can be implemented
by a client. So if there are some methods which are not relevant, then they
should either be removed or they should be placed in another interface. It
should be segregated such that an interface performs their actions specific
to that interface.
Let's take an example, so let's say we have a feature where we want to
process the delivery of an order. So what does this mean? So let's say we
need to process the order. We need to notify the seller to pack the order
and send it for delivery. So this is a class diagram right which implements
this feature, so we have a seller class and a product class and the delivery
processing here is an interface right which has methods like place order.
You notify the seller, you package the order and you deliver it. Now Clients
can implement this delivery processing interface and write definitions for
each of these methods right to implement this feature of processing the
delivery.
However, there is one issue with this interface right: let's say we have
online orders or we have orders in which you have a digital product, for
example an e-book right such orders. You need not actually pack them right
and you need not deliver them to a specific physical address. So if there is
a client who wants to implement a delivery of an e-product right, these two
methods are irrelevant to them right. Well, they can, of course, implement
the delivery processing interface, but not have any meaningful
implementations for package order and delivery.
So, as this principle suggests, it is necessary to segregate or split this
interface, the delivery processing interface right. So what we can do is
create two interfaces. One is for a physical delivery and the other is for an
online delivery right and the physical delivery Processing interface Remains
the Same as the previous one right, where you have placed an order by
notifying the seller. You package the order and you deliver it to a specific
address, whereas an online delivery processing interface can have, for
example, the place order and the notify seller can be the same right, but
you do not require a package order or a deliver order method. So now, if a
client wants to implement an online delivery order, they just have to
implement the online delivery processing interface and if some other client
wants to implement physical delivery, then just need to implement the
physical delivery processing interface. So the key idea to note here is that it
is necessary that we segregate or split our interfaces such that each
interface performs a particular function right. So we should not force a
client to implement any of our methods which are irrelevant to them in an
interface.
Now, let's look at the final principle, which is the dependency inversion
principle, so this principle states that a client or when we write code we
should always prefer abstractions or interfaces over specific
implementations. We should always prefer abstractions over
implementations. So what does this mean right?
So, let's take an example, so let's say we want to implement a feature
where a seller should receive payment of their products sold through the
seller portal right so to implement this feature, I of course need a seller
class right with seller attributes and some Seller methods for adding and
deleting a seller and bank account is one of the attributes of the seller right
and a bank account can have Account Details like the number, the branch,
the balance and all of that right.
So now let's say I want to extend this feature and now let's say I want to
receive payment via other mediums like paytm, Google, pay or UPI Etc
right, so I will Implement classes for each of these payment methods and
now I want to add the payment method for this seller as let's say, UPI right,
but now the issue is so then I will have to create - or I might have to add
another attribute for UPI here right because currently seller is Tightly
coupled with the bank account class now. Similarly, if I want to have the
seller associate with other payment methods, like Google pay, paytm UPI, I
need to couple the seller with these classes or these objects as well right and this is an issue right - and this is making my code unnecessarily
complex. This can be fixed by using an interface.
So what are design patterns ? Design patterns are nothing but descriptions
of how objects and classes should communicate with each other to solve a
general design problem in a particular context. Right so, as we saw earlier,
design patterns have evolved over many years and several experienced
Developers realize that these patterns appear again and again in code and
hence these patterns have been generalized and these descriptions are
known as design patterns.
So what are elements of a design pattern? So first we need to identify the
problem for which a particular design pattern can be applied to. So we
need to know when to apply the design pattern and in what context right.
So that is the first thing we need to know. Then we apply the design pattern
that forms part of our solution and this solution describes the elements that
make up the design. So what are the relationships between classes or
between objects? How do they collaborate with each other, so these are
different aspects of the solution and this solution serves as a template right
which can be applied in different situations. And, finally, when we apply a
design pattern, it has certain consequences right. We need to understand
what the trade-offs are, what the costs are, what the benefits are and
whether we actually need to apply the design pattern or not in a particular
context,
now that we know what the elements of a design pattern are let's look at
certain types of design patterns, so there are three types of design
patterns. One is known as a creational design pattern. It is used during the
process of object creation. So whenever we want to create objects in
certain situations, certain creational design patterns can be used, and this
will give us more flexibility as well as help us reuse existing code. We will
look at examples of creational design patterns. Another type of design
pattern is known as the structural design pattern, so structural design
patterns, it explains how we can assemble objects and classes into larger
structures again with the aim of making our code more flexible and efficient,
and the third type of design patterns are known as behavioral design
patterns, these patterns ensure that there is effective communication
between objects and classes, as well as it ensures that the responsibility
between objects are distributed properly right. We will be looking at
examples of each of these types of design patterns.
we'll be looking at two types of creational design patterns, the factory
design pattern and the Builder design pattern.
So, let's look at the factory design pattern first, so let's take an example of
the seller portal itself and let's say I want to implement a functionality where
I need to deliver a package using a particular Courier Service. So I need to
deliver a package using a particular Courier Service, so looking at this
functionality, you realize that you will need two objects or two classes. One
is the delivery which delivers the package right using a particular Courier
Service. So Courier forms another class and we see that there's an
association between delivery and Courier, so the delivery class has a
method called deliver which takes Courier as an argument. So what
changes will you make to include the functionality of adding, let's say,
International couriers? We will create separate classes which extend The
Courier class right so we'll create a class called National Courier, we'll
create another class called International Courier right, which corresponds
to sending something nationally and internationally. And in addition, we will
also create classes which extend the delivery class, one which corresponds
to National delivery, another which corresponds to international delivery,
and in this case we have an additional method called create Courier, which
returns a courier object right. So the delivery class has a Creator method
which creates or which returns a courier object, and so the national delivery
class will return a national Courier. The create courier method will return a
national Courier object and similarly, the international delivery class has a
method called create Courier, which returns an international Courier object
right. So the responsibility of creating objects has now been dedicated to
these classes, the national delivery and the international delivery, and to a
specific method known as the factory method. So in this case, the create
Courier method is known as a factory method which actually creates The
Courier objects.
So what is the advantage of using this Factory design method? Let's say I
want to extend my Courier Services to let's say local couriers right, so all
that I have to do is create the appropriate classes and call the factory
method, and it will create The Courier Service for me. so in this way it
makes the code more understandable and more extendable. Now that we
have seen what the factory design pattern is, let's look at some of the pros
and cons. So what are the pros? What are the advantages of using this
design pattern? One is that this helps us follow the single responsibility
principle so recall that single responsibility means that each class has a
single functionality or responsibility to perform. And second, it follows the
open, close principle which states that classes should be open to extension
but closed for modification. Now, what are some cons of using this design
pattern, so you might have observed that the code can become
complicated right. There can be a lot of new subclasses which are added,
and this can make the code a little more difficult to understand. So, hence
we need to decide or make a trade-off as to whether we need to apply this
Factory design pattern or not.
Let's look at another creational design pattern known as the Builder design
pattern. So let's take an example. So let's say I have a book class and I
need to create a book object with some mandatory parameters and some
other optional parameters. So in this case let's say that ISBN title and cost
are mandatory, whereas author published and description are optional
fields right. So, in order to create such book objects, I need to call different
types of Constructors right.
So let's see how we can use the Builder design pattern to solve this
problem. So the Builder design pattern tells us to extract the object
construction code out of its own class right. So we separate out the object
construction code and we move it to a separate object, known as a builder
object right. So if we take the example of the book class, we create another
class called Builder which has the same Fields as the book class right and
in addition to that, it has methods like author. So this method is the method
which initializes the author field. The published method is nothing but the
method which initializes the published field and the same for description.
So for each of the optional parameters. We have additional methods right
which initialize those fields and we have a build method which finally builds
the object and returns a book.
So what are the pros and cons of the Builder design pattern? So the pros
are one: it helps us construct objects step by step right, so we saw that we
can construct this book object by initializing each parameter right so as
opposed to calling lengthy Constructors right, and the other Advantage is
that it follows the single responsibility principle Of separating the task of
object, Creation with other responsibilities right, so the Builder class takes
care of building the object, and the actual object now can focus on other
aspects required of that class. Now what are some drawbacks or
disadvantages of this design pattern? Well, the key disadvantage is that the
code may become more complicated right. So, as we saw, we need to
create another Builder class with the same parameters right and additional
functions as well. And if you feel that in your code you do not have many
mandatory and optional parameters, then it might be okay to not use this
design pattern.
The first structural design pattern we are going to look at is the facade
design pattern. So let's say you have to create several objects and perform
several steps. So let's say you are to initialize many objects and for a
particular task. You need to execute methods in the correct order. Give the
right parameters Etc. Right or you need to have used an existing
complicated Library function right and the clients or others who are going to
reuse your code will face an issue all right. They will have to know details
about which all are the different objects to be created. What are the
necessary Library, functions, Etc, right, and this makes it difficult for the
client to use your code.
So, let's take an example from the seller portal itself: let's say after a buyer
places an order. The system should do the following task: the system
should create an order order. The system should notify the appropriate
seller, prepare the packaging and send the item out for delivery. Right so
here we see that there are several steps which need to be performed.
So this problem can be solved using the facade design pattern, so facade
design pattern. It provides a simple interface to a library or a complex set of
classes. So, for example, let's say there are several functions and classes
which need to be called right for a particular operation. So in the facade
design pattern you create a class which has a method which calls all the
respective or required functions and places them in a single method. So in
this case, do something calls all the appropriate methods in each of the
individual classes and now clients do not have to remember each of the
individual function calls, but we'll just have to call do something with the
necessary parameters.
So what are the pros and cons of using the facade design pattern? So one
advantage is, as we saw, that it helps us isolate the complexity of the code
or the different libraries that we have and expose clients to just a single
method or function. The disadvantage of using the facade design pattern is
that the facade is tightly coupled to other objects and because of this
maintenance becomes more difficult. So, for example, in this case, we see
that the delivery facade is coupled to the order, the seller, the package and
the delivery classes right and if any change happens in any of these
objects or these functions, then we need to make appropriate changes in
the delivery Facade class as well.
Now, let's look at the next design pattern, which is the adapter design
pattern. So, let's look at the problem: let's take the example of the Amazon
Seller portal itself and let's say some products have cost in dollars or euros
and hence conversion to rupees is needed. Let's say we have a product
class and we have a library or a class called a conversion calculator. So the
conversion calculator is an existing library for which we do not have a
controller right. So this product class cannot directly access the conversion
calculator class or it has an incompatible interface to that of the product
class. Right so, let's say a conversion calculator is an interface which is not
compatible with products. So product cannot directly access the conversion
calculator due to various reasons. So in such cases, the adapter design
pattern comes in handy right.
So what is the adapter design pattern so between so let's say, the client
wants to call method B right and the client cannot directly call method B. So
what we can do is create an adapter class right and what the adapter class
does is It provides a wrapper or it provides a link between the client and the
adapter. So what the client will do is call the adapters method and the
adapter in turn will call the adaptees method right and these methods might
be incompatible to each other. But that issue of incompatibility is taken care
of by the adapter right, so the adapter wraps one of the objects to hide the
complexity of what is happening behind the scenes right and the client
need not be aware of. You know what are the complexities involved? The
adapter takes care of that now.
So let's look at some of the pros and cons of using the adapter design
pattern. So one advantage is that we are following the single responsibility
principle right. So, in our case, we were, we separated the code to convert
from dollars to rupees or Euros to rupees from the actual business logic of
the product class, which is to add products edit delete products right in that
way, we are following the single responsibility principle, the Other
Advantage is that if we want to add new types of adapters - let's say for
other currencies, then this can be done easily, and this follows the open,
close principle where we say that a class should be opened for extension.
So we can extend the functionality of these classes by adding new types of
adapters. The disadvantage is that the complexity of code can increase. So
let's say we are adding an adapter, so we have to add a new class and add
appropriate methods, and if we were able to make changes in the product
class or maybe get access to the conversion calculator, then we need not
create a separate class.
So, let's look at one behavioral design pattern known as the iterator design
pattern. So what is the problem which this design pattern is trying to solve?
So we use different types of collections right in our algorithms. When we
store data, it can be lists, it can be queues, stacks and trees, and a
common operation which we have to do is to access as well as iterate,
through various elements in this collection. So it can, for example, it can be
a list of products right which can be stored, maybe as a list it can be a list of
orders. It can be a list of deliveries right. So all of these are Collections and
a common set of operations are accessing them as well as iterating
through these various elements. Now, as a client, I am concerned only with
accessing these elements right, I am not really interested in how these
elements are stored, or what is the underlying data structure which stores
these collections, so the iterator design pattern helps us to separate the
behavior of how The elements are accessed into a separate object called
an iterator,
so you all must be familiar with the iterator interface in Java right and the
iterator interface in Java has two key functions. One is has next, which
returns true If the iteration has more elements and next, which Returns the
next element in the iteration
Now, let's look at some pros and cons of using this design pattern. So what
are some advantages? One is that it follows the single responsibility
principle, where we separate the axis of elements from other functionalities.
So even in our example, we saw that the accessing the elements has been
delegated to a separate class known as the iterator right. Another
Advantage is that it helps us implement the open, close principle. So let's
say I want to implement a new type of iterator right, so I can create or
extend or implement the iterator interface in Java or create my own iterator
right, and this will help me. I trade through different or new types of
collections. What is the disadvantage? So one disadvantage is that let's
say we have simple collections like maybe an array right. It might be an
overkill for you to create a separate iterator class for simple applications
and which have simple collections.
Another type of behavioral design pattern is the Observer design pattern.
So let's say you want to implement a feature where you want to notify a
particular set of buyers when a new product is launched right and most of
you are familiar with such notifications, so you might be getting such
notifications in several of the apps, which you Use right so, let's say you
have subscribed to a channel on YouTube and the channel posts, a new
video right, and if you have subscribed to Notifications, you would get a
notification that this particular channel has uploaded a new video right. So
as a subscriber you get a notification when there are updates right, and I do
not want to send this notification to all users of my system, but only to those
who have subscribed to get notifications right.
So how do I solve this problem? So this problem can be solved using the
Observer design pattern. So what happens? Is that the subject object? It
maintains a list of Observers and as and when there are updates it notifies
The subject object & that notifies All The Observers for any updates or
changes right. So let's look at the class diagram for The Observer design
pattern, so we have a subject class right, which maintains a collection of
Observers. The subject class can register Observers and we see that the
Observer is an interface right which has a function called update and there
can be other classes which implement this interface right and implement
the update method. And now the subject has a method called notify.
Observers which simply iterates over the collection and calls the
appropriate update function.
Now, let's look at another design pattern known as the strategy design
pattern. So let's say you want to implement a feature where you want to
process shopping orders based on different strategies. For example, one
strategy is first in first out where the orders which come first, they are
processed first. Another type of strategy can be based on priority right or
based on type of user. So, let's say Prime users or super users receive a
higher priority and hence their orders are processed first, whereas normal
users orders are processed later right. So to solve this problem, you can
use the strategy design pattern.
So in the strategy design pattern you extract different strategies or
algorithms into separate classes. So, for example, you can have a priority
class right and you can have another class, which is the first and first out
class right and the original class, which is known as the context it delegates
this work of implementing this algorithm to the strategy object right. So in
this case, you can have two strategies like strategy A and strategy B which
implement the interface strategy and the algorithm is present in the execute
method right so the original class delegates the work of implementing the
strategy or the algorithm to the strategy. Interface.
Now, let's look at some of the pros and cons of this strategy. So what are
some pros? So, as we saw the strategy design pattern, it isolates the
implementation details of the algorithm right. So each class will have a logic
for a specific strategy and we also saw that it helps implement the open,
close principle right. We can introduce new strategies without changing the
existing classes or methods, and what is the disadvantage when, let's say
our application does not require many algorithms or strategies we just have
one or two strategies right then we need not actually implement the
strategy design pattern.
Download