Hi.
Welcome to a new section of this video course.
Template momento and interpreter design pattern in this section we will see the next three behavioral
design patterns.
The difficulty is being raised does now we will use combinations of structural and creation or patterns
to better solve the objective of some of the behavioral patterns.
We will start with template design pattern a pattern that looks very similar to strategy pattern but
that provides greater flexibility momento design pattern is used in 99 percent of applications we use
every day to achieve undo functions and transactional operations.
Finally we will write a reverse Polish notation interpreter to perform simple mathematical operations.
Let us start with the template design pattern.
In this video we are going to write an algorithm that is composed of three steps and each of them returns
a message.
The first and third steps are controlled by the template and just the second step is deferred to the
user.
The template pattern is one of those widely used patterns that are incredibly useful especially when
writing libraries and frameworks.
The idea is to provide a user some way to execute code within an algorithm.
In this section we will see how to write idiomatic go template patterns and see some go source code
words wisely used.
We will write an algorithm of three steps where the second step is delegated to the user while the first
and third aren't the first and third steps of the algorithm represent the template.
While with the strategy pattern we were encapsulating algorithm implementation in different strategies
with the template pattern.
We will try to achieve something similar but with just part of the algorithm the template design pattern
lets the user write a part of an algorithm while the rest is executed by the abstraction.
This is common when creating libraries to ease in some complex task or when reuse ability of some algorithm
is compromised by only a part of it.
Imagine for example that we have a long transaction of H TTP requests we have to perform these steps.
First we authenticate user and then authorize them.
Next we retrieve some details from a database and make some modification.
Lastly we send the details back in a new request.
It wouldn't make sense to repeat steps one to five in the user's code every time he needs to modify
something on the database.
Instead steps 1 2 3 and 5 will be abstracted in the same algorithm that receives an interface with whatever
the fifth step needs to finish the transaction.
It doesn't need to be an interface either.
It could be a callback.
The template design pattern is all about reuse ability and giving responsibilities to the user.
So the objective for this pattern are listed here differ a part of the algorithm of the library to the
user and improve reuse ability by abstracting the parts of the code that are not common between executions.
A brief description of what the template pattern has to do is to define a template for an algorithm
of three steps that defers the implementation of the second step to the user.
Here are the requirements and acceptance criteria for our example.
So each step in the algorithm must return a String and the first step is a method called first and returns
the string hello.
While the third step is a method called Third and returns the string template.
Then the second step is whatever string the user wants to return.
But it's defined by the message retriever interface that has a message string method.
Finally the algorithm is executed sequentially by a method called execute algorithm and returns the
strings returned by each step joined in a single string by a space.
Now let's move on to the unit tests for the simple algorithm.
Now we will focus on testing the public methods only.
This is a very common approach.
All in all.
If your private methods aren't called from some level of the public ones they aren't called at all.
We need to interfaces here one for the template implementers and one for the abstract step of the algorithm.
As you can see I have created a folder called template and I have two files created here with the names
template dot go and template underscore test dot go.
So let's open template dot go here.
Let's add the package name and type interface a template implement or will accept a message retriever
interface to execute as part of its execution algorithm.
We need a type that implements this interface called template.
We will call it template.
I am p l let's add the code for the template implement a struct.
So our first test checks the fourth and fifth acceptance criteria.
We will create the test struct type that implements the message retriever interface returning the string
world and has embedded the template so that it can call the execute algorithm method.
It will act as the template and the abstraction.
Let's save this file for now and move on to template test.
Dot go here we have named the package as template and imported strings and testing.
Since this is a test first defined the test struct type.
In this case the part of the algorithm deferred to us is going to return the world text.
This is the string we will look for later in the test.
Doing a check of type is the word world present in the string.
Take a close look the test struct embeds a type called template which represents the template pattern
of our algorithm.
When we implement the message method we are implicitly implementing the message retrieval interface.
So now we can use test struct type as a pointer to a message retrieval interface.
Next let's add the code for the function test template algorithm in the test we will use the type we
have just created when we call the execute algorithm method.
We need to pass the message retrieval interface as the test struct type also implements the message
retriever interface.
We can pass it as an argument but this is not mandatory of course the result of the execute algorithm
method as defined in the 5th acceptance criterion must return a string that contains the return value
of the first method the returned value of test struct.
That is the world string and the return value of the third method separated by space.
Our implementation is on the second place.
That's why we check that the space is prefix and suffix on the string world.
So if the return string when calling the execute algorithm method doesn't contain the string world the
test fails.
This is enough to make the project compile and run the tests that should fail.
Let's save this file and open the terminal type the command go test iPhone V.
As expected the test fails.
Go time to pass the implementation of this pattern as defined in the acceptance criteria we have to
return the string hello in the first method and the string template.
In the third method that's pretty easy to implement open the templates not go file and let us modify
the code here.
Let me add proper indentation.
Also make sure to change the type template interface to temper later as we can not have to type with
the same name.
Save the file with this implementation.
We should be covering the second and third acceptance criteria and partially covering the first criterion
that is each step in the algorithm must return a String to cover the fifth acceptance criterion.
We define an execute algorithm method that accepts the message retriever interface as an argument and
returns the full algorithm.
A single string done by joining the strings returned by the first message string.
And third methods the strings dot joint function has this signature.
It takes an array of strings and joins them placing the second argument between each item in the array.
In our case we create a string array on the fly to pass it as the first argument.
Then we pass a whitespace as the second argument with this implementation.
The tests must be passing already.
Let us save the file navigate to the terminal and run the test.
Go test hyphen v enter the tests passed the test has checked that the string world is present in the
returned result which is the hello world template message Hello text was the string returned by the
first method the world string was returned by our message retrieval implementation and template was
the string returned by the third method.
The white spaces are inserted by ghost strings dot join function but any use of the template implementation
dot execute algorithm type will always return Hello something.
Template in its result.
This is not the only way to achieve the template design pattern.
We can also use an anonymous function to give our implementation the execute algorithm method.
Let us write a test in the same method that was used previously so open the template test dot go file
and add the code at the bottom of the file.
Our new test is called using anonymous functions.
We have also extracted the checking on the test to an external function to reuse it in this test.
We have called this function expected or error because it will fail with an error.
If the expected value isn't received in our test we will create a type called Anonymous template that
replaces the previous template type the execute algorithm method of this new type accepts the func method
string type that we can implement directly in the test to return the string world.
Now let's save the file and move to the templates not go file.
Here we are the anonymous template type structure.
The only difference with the template type is that the execute algorithm method accepts a function that
returns a string instead of a message retrieval interface.
Let us run the new test save the file and go back to the terminal.
Let us run the test command.
Go test hyphen V.
As you can read in the output of the test execution the error is thrown on the using anonymous function
test which is what we were expecting.
Now open the templates dot go let's write the implementation by modifying the return statement in the
anonymous template type.
The implementation is quite similar to the one in the template type.
However now we have passed a function called f that we will use as the second item in the string array
we used on joint function as f is simply a function that returns a string.
The only thing we need to do with it is to execute the proper place which is the second position in
the array.
Don't forget to save the file for the changes we made.
Let's open the terminal and run the tests again.
Awesome.
Now we know two ways to implement the template design pattern.
Now a question which may arise here is that how do you avoid the modifications on the interface.
The problem of the previous approach is that now we have two templates to maintain and we could end
up duplicating code.
What can we do in the situation that we cannot change the interface we are using our interface was the
message receiver but we want to use an anonymous function now.
Well do you remember the adapter design pattern.
We just have to create an adapter type that accepting a function string type returns an implementation
of the message receiver interface.
We will call this type template adapter.
Let's open templates dot go and add the template adapter.
As you can see the template adapter type has a field called My bunk which is of the type.
Func string.
We have also defined adapter as private because it shouldn't be used without a function defined in the
my func field.
We have created a public function called The Message retrieval adapter to achieve this.
Let's save the file and go back to the Template test dot go.
And here let's add the test.
So this is how our test should more or less look like.
Look at the statement where we called The Message retriever adapter method.
We passed an anonymous function as an argument defined as func string.
Then we reuse the previously defined template type from our first test to pass the message retrieve
or variable.
Finally we checked again with the expected or error method.
Take a look at the message retrieve or adapter method it will return a function that has nil value.
If strictly following the test driven development rules we must do tests first and they must not pass
before implementation is done.
That's why we returned nil on the message retrieve or adapter function.
So let's run the tests first.
Save the file and move to the terminal run the command go test hyphen V.
The test fails on line 42 of the code and it doesn't continue.
Again depending on how you wrote your code the line representing your error could be somewhere else.
We stop test execution because we will need a valid message receiver interface.
When we call the execute algorithm method but the implementation of the adapter for our template pattern
we will start with message retriever adapter method.
So let go back to the Template dot go.
Let us modify the message retrieval adapter.
It's very easy right.
You could be wondering what happens if we pass nil value for the F argument.
Well we will cover this issue by calling the my func function.
Now let's modify the type template adapter struct so the adapter type is finished with this implementation.
When calling the message function we check that we actually have something stored in the my func function
before calling.
If nothing was stored we return an empty string.
Now our third implementation of the template type using the adapter pattern is done save the file and
move to the terminal let us run the test command as you can see we have passed the test.
Wonderful.
Now let's see how to look for the template pattern and go source code the source packaging goes source
code can be considered a template implementation of a sort algorithm as defined in the package itself
the source package provides primitives for sorting slices and the user defined collections.
Here we can also find a good example of why go authors aren't worried about implementing generics sorting
the lists is maybe the best example of generic uses in other languages.
The way that go deals with this is very elegant too.
It deals with this issue with an interface.
Let me show you this interface.
I have already created the file sort underscore.
Example dot go.
Let me open this.
This is the interface for lists that need to be sorted by using the source package.
In the words of go's authors a type typically is a collection that satisfies sort interface can be sorted
by the routines in this package.
The methods require that the elements of the collection be enumerated by an integer index.
In other words write a type that implements this interface so that the sort package can be used to sort
any slice the sorting algorithm is the template and we must define how to retrieve values in our slice.
If we peak in the sort package we can also find an example of how to use the sorting template but we
will create our own example here add the lines of code as I do.
First we have done a very simple type that stores an entire list.
This could be any kind of list usually a list of some kind of struct.
Then we have implemented the sort.
Don't interface interface by defining the land swap and less methods.
Finally let's write the main function.
The main function creates an unordered list of numbers of my list type.
We print the list that we created unordered and then we sorted the sorted out sort.
Method actually modifies our variable instead of returning a new list.
So beware.
Finally we print again.
The resulting list.
Now we are ready to see the console output of this main method.
Save the file and open the terminal.
Run the command go run.
Sort.
Example dot go the sword dot sword function has sorted our list in a transparent way.
It has a lot of code written and delegates land swap and less methods to an interface like we did in
our template.
Delegating to the message retriever interface.
Superb.
Now let me summarize the template design pattern.
So we wanted to put a lot of focus on this pattern because it is very important when developing libraries
and frameworks and allows a lot of flexibility and control to users of our library.
We have also seen again that it's very common to mix patterns to provide flexibility to the users not
only in a behavioral way but also structural.
This will come in very handy when working with concurrent apps where we need to restrict access to parts
of our code to avoid races.
In this video we have learned about the template design pattern in the next video.
We will be exploring about momento design pattern.