Before concluding this lesson, let's look at a few more patterns. And
although it will take too long to cover them in detail, I
would like to at least mention and quickly discuss a few more
of these more commonly-used patterns. In fact, some of the patterns that
I will discuss, you might have used yourself. Maybe without knowing their
name or the fact that they were design patterns. So let's start
with a Visitor pattern, which is a way of separating an algorithm
from an object structure on which it operates. And a practical result
of this separation is the ability to add the new operation
to exist in object structures, without modifying the structures. So, basically
what this pattern does, is to allow for defining and easily
modifying set of operations to perform on the objects of the collection.
And the typical usage of this is, for example, when you're
visiting a graph, or a set of objects, and you want
to perform some operations on these objects. By using a visitor
pattern, you can decouple the operation
from the objects. Although not straightforward,
this pattern is very, very useful. So, I really encourage you
to look at it in more detail and get familiar with it.
The second pattern I want to mention is the decorator pattern.
The decorator pattern is basically a wrapper that adds functionality to a
class. So the way in which it works, is that you
will take a class, you will build a class that basically wraps
this class. So it reproduces the functionality of the original class, but
it also adds some functionality. And for all the functionality that was
already in the original class, it will simply invoke this
functionality and for the new one, you will implement it
using the services of the class. And a nice property
of the decorator pattern is that it's stackable. So you can
add decorators on decorators on decorators, and further increase the
functionality provided by your class. The iterator is another very
commonly-used pattern. And, you probably use this one yourself because,
it's also part of many standard libraries. What the iterator allows
you to do, is basically to access elements of a collection
without knowing the underlying representation. So the iterator will allow you
to just go through a set of objects without worrying about
how the objects are stored. So you basically just ask the
iterator to give you the first object, the next object and
so on. Another very commonly-used pattern is the observer pattern. And
this pattern is very useful when you have an object of
interest and a set of other objects that are interested in
the changes that might occur in this first object. So
what the observer pattern allows you to do is to register
these objects, so that they let the system know that
they're interested in changes in this first object. And then, every
time that there is a change, these other objects will
be automatically notified. So basically,
the observer pattern allows for notifying
dependents when an object of interest changes. If you want
an example of this, just think about the file system and
imagine having a folder. All the views of this folder will
want to be notified every time that there's a change in
the folder because they need to refresh. So instead of continuously
checking the state of the folder, they will just register and basically
say, hey, we're interested in knowing when something changes in this
folder. And when something changes in the folder, they will be automatically
notified. So it will be some sort of a push notification
instead of a pull notification, if you are familiar with that terminology.
Finally the proxy pattern is a pattern in which a surrogate
controls access to an object. In other words, we have our object,
and we have our proxy here. So all the requests to the
object will go through the proxy that will then forward them. And
all the responses from the object will also go through the
proxy. They will then forward them to the original requester. So what
the proxy allows you to do is to control how this object,
that is behind the proxy, is actually accessed, for example, by filtering
some calls. So in a sense, the proxy allows use
for masking some of the functionality of the object that
is behind the proxy. And there's many, many, many more
useful patterns. That can help you when designing and implementing
the system. So once more, I really encourage you to
have a look at the book, to look at the
resources online, and to really get more familiar with these
patterns, and to try to use them in your everyday work.