Hello.
We are now at the last video of this section observe a design pattern in the previous video.
We looked at mediator design pattern in this video.
We will develop the simplest possible application to fully understand the roots of the observer pattern.
We are going to make a publisher struct which is one that triggers an event so it must accept new observers
and remove them if necessary.
When the publisher struct is triggered it must notify all its observers of the new event with the data
associated.
We will finish the common gang of four design patterns with my favorite the observer pattern also known
as publish subscriber or publish listener with the state pattern.
We defined our first event driven architecture but with the observer pattern we will really reach a
new level of abstraction.
So the idea behind the observer pattern is simple to subscribe to some events that will trigger some
behavior on many subscribed types.
Why is this so interesting.
Because we uncouple an event from its possible handlers for example imagine a log in button.
We could code that when the user clicks the button the button color changes and action is executed and
the form check is performed in the background.
But with the observer pattern the type that changes the color will subscribe to the event of the clicking
of the button.
The type that checks the form and the type that performs an action will subscribe to this event to the
observer pattern is especially useful to achieve many actions that are triggered on one event.
It is also especially useful when you don't know how many actions are performed after an event in advance
or there is a possibility that the number of actions is going to grow in the near future to resume.
Do these steps First provide an event driven architecture where one event can trigger one or more actions
and uncoupled the actions that are performed from the events that triggers them.
Provide more than one event that triggers the same action the requirements must tell us to have some
type that trigger some method in one or more actions.
So we must have a publisher with a notify observer's method that accepts a message as an argument and
triggers a notify me method on every observer subscribed.
Next we must have a method to add new subscribers to the publisher.
Lastly we must have a method to remove new subscribers from the publisher.
Now let's move on to the unit tests.
Maybe you have realized that our requirements defined almost exclusively the publisher type.
This is because the action performed by The Observer is irrelevant for the observer pattern.
It should simply execute an action.
In this case the notify method that one or many types will implement.
So let's define this only interface for this pattern.
Open the observer dot go file and add these lines of code.
I have declared the package name and the observer interface.
The Observer interface has a notify method that accepts a string type that will contain the message
to spread.
It does not need to return anything but we could return an error if we want to check if all observers
have been reached when calling the publish method of the publisher structure to test all the acceptance
criteria.
We just need a structure called publisher with three methods.
So let's create these three methods.
The publisher structure stores the list of subscribed observers in a slice field called Observer's list.
Then it has the three methods mentioned in the acceptance criteria.
The ad observer method to subscribe a new observer to the publisher.
The remove observer method to unsubscribe an observer and notify observers method with a string that
acts as the message we want to spread between all observers.
With these three methods we have to set up a route test to configure the publisher and three sub tests
to test each method.
We also need to define a test type structure that implements the observer interface.
This structure is going to be called Test observer save this file and go to the Observer underscore
test dot go file.
Let's add the test observer struct here.
The test observer structure implements the observer pattern by defining a notify string method in its
structure.
In this case it prints the receive message together with its own observer I.D. then it stores the message
in its message field.
This allows us to check later if the content of the message field is expected.
Remember that it could also be done bypassing the testing dot t pointer and the expected message and
checking within the test observer structure.
Now we can set up the publisher structure to execute the three tests.
We will create three instances of the test observer structure.
Let's do it.
Also let me add the publisher we have given a different idea to each observer so that we can see later
that each of them has printed the expected message.
Then we have added the observers by calling the ad observer method on the publisher structure.
Let us write an ad observer test.
It must add a new observer to the Observer's list field of the publisher structure.
We have added three observers to the publisher structure so the length of the slice must be three.
If its not three the test will fail the remove observer test will take the observer with I.D. 2 and
remove it from the list.
So next we add the remove observer test cool.
After removing the second observer the length of the publisher structure must now be two.
We also check that none of the observers left have the I.D. too because it must be removed.
The last method to test is the notify method when using the notify method.
All instances of Test observer structure must change their message field from empty to the past message
which is hello world in this case.
First we will check that all the message fields are in fact empty before calling the notify.
Observers test.
Let's add the code for this.
Using a false statement we are iterating over the Observer's list field to slice in the publisher instance.
We need to make a type casting from a pointer to an observer to a pointer to the test observer structure
and check that the casting has been done correctly.
Then we check that the message field is actually empty.
The next step is to create a message to send.
In this case it will be hello world and then pass the message to the notify observers method to notify
every observer on the list.
Currently observers 1 and 3 only.
So here's the code.
Okay.
After calling the notify observers method.
Each test observer tests in the Observer list field must have the message Hello World stored in their
message field.
Again we use a for loop to iterate over every observer of the observers list field and we typecast each
to a test observer test.
Remember that test observer structure doesn't have any field as it's an interface.
We could avoid typecasting by adding a new message method to observer instance and implementing it in
the test observer structure to return the contents of the message field.
Both methods are equally valid.
Once we have typecast it to a test observer method called Print observe a variable as a local variable.
We check that each instance in the Observer lists structure has the string Hello World stored in their
message field.
It's time to run the tests that must fail all to check their effectiveness in later implementation.
Save the file and move to the terminal run the command go test hyphen v something isn't working as expected.
How is the notify method passing the test.
If we haven't implemented the function yet take a look at the test of the notify method again.
Right over here the test iterate over the observers list structure and each failed call is inside this
for loop.
If the list is empty it won't iterate so it won't execute any failed call.
Let's fix this issue by adding a small non empty list check at the beginning of the notify test done
save the file and now we will rerun the tests to see if the test subject or notify method is already
failing
nice.
All of them are failing and now we have some guarantees on our tests.
We can proceed to the implementation.
Our implementation is just to define the add observer the remove observer and notify observers methods.
Let's open the observer dots.
Go file and modify the add observer method.
The add observer method adds The Observer instance to the observers list structure by appending the
pointer to the current list of pointers.
This one was very easy.
The add observer test must be passing now but not the rest.
Or we could have done something wrong now saved the file and moved to the terminal to run the test.
Go test hyphen V.
Whoops.
We don't need to include f empty in the import statement.
Let's add it as a comment for now.
Fine let's save the file and again run the test.
Excellent.
Just the add observer method has passed the test so we can now continue to remove observer method.
Let's go back to our file and now modify the remove observer method.
Perfect.
Remove observer method will iterate for each element in the Observer's list structure comparing the
observer Object o variable with the one stored in the list if it finds a match it saves the index in
the local variable index to remove and stops the iteration.
The way to remove index is on a slice and go is a bit tricky.
First we need to use slice indexing to return a new slice containing every object from the beginning
of the slice to the index.
We want to remove that is not included then we get another slice from the index we want to remove not
included to the last object in the slice.
Finally we joined the previous two slices into a new one.
That is the append function for example in a list from one to 10 in which we want to remove the number
five we have to create a new slice.
Joining a slice from 1 to 4 and a slice from 6 to 10 this index removal is done with the append function
again because we are actually appending two lists together.
Just take a closer look at the three dots at the end of the second argument of the append function.
The append function adds an element.
The second argument to a slice which is the first but we want to spend an entire list.
This can be achieved using the three dots which translate to something like keep adding elements until
you finish the second array.
Okay let's run this test now.
We continue in the good path.
The remove observer test has been fixed without fixing anything else.
Now we have to finish our implementation by defining the notify observers method.
Let's go back to the Observer dot go file and this time we modify the notify observer method.
And since we are using f empty we need to on comment.
The import statement the notify observers method is quite simple because it prints a message to the
console to announce that a particular message is going to be passed to the observers.
After this we use a for loop to iterate over Observer's list structure and execute each notify string
method by passing the argument M after executing this.
All observers must have the message Hello World stored in their message field saved the file again and
navigate to the terminal.
Let's see if this is true by running the tests.
Excellent.
We can also see the outputs of the publisher and observer types on the console.
The publisher structure prints the message hey I have received the message Hello World and I'm going
to pass the same message to the observers.
After this all observers print their respective messages.
Hey I'm observer one and I've received the message Hello World and the same for the third observer in
this section we have unlocked the power of event driven architectures with the state pattern and the
observer pattern.
Now you can really execute asynchronous algorithms and operations in your application that respond to
events in your system the observer pattern is commonly used in you eyes Android programming is filled
with Observer patterns so that the Android SDK can delegate the actions to be performed by the programmers
creating an app.
So we had a wonderful journey exploring the behavioral design patterns.
I am sure you had fun with go and these concepts have strengthened your programming knowledge.
I hope to see you in our next part go concurrency patterns where we will dive into some advanced design
patterns in go till then goodbye.
Let's go.