Bummer! This is just a preview. You need to be signed in with a Pro account to view the entire video.
Start a free Basic trial
to watch this video
Java 8 makes functions a first class citizen. Look at how quickly the pattern can be applied by embracing them.
Learn more
-
0:00
We saw the power of rapidly being able to implement the pattern
-
0:03
by looping through subscribers using our parameter as list.
-
0:07
Well there is, in fact, a growing movement to make that even quicker.
-
0:10
Functional programming has been around for a long time, but
-
0:13
it's relatively new to the Java world.
-
0:15
So there are newer patterns forming that are leaning on this powerful,
-
0:18
succinct approach.
-
0:19
Let's give it a whirl.
-
0:22
If you haven't played around with Java 8's functional programming side of things,
-
0:25
I hope that this example will encourage you to explore it a bit.
-
0:29
Now our final project for this workshop is going to explore an Olympics tracking app.
-
0:33
So we have a class called GoldMedalReporter.
-
0:37
Let's open that up.
-
0:38
So under gold-watcher here, there's GoldMedalReporter, and
-
0:42
it's a pretty bare bones class, right?
-
0:44
It's just for demo purposes,
-
0:45
it has a single method, it's called reportWin, and basically,
-
0:49
it just says the gold medal was awarded to whatever country was best at it, right?
-
0:53
So, we have all these other tools that we would like to integrate with this, right?
-
0:57
So, over here under tools, we have this, what is a Twitter client called Tweeter.
-
1:02
You can imagine that this can x out to the API, but basically,
-
1:05
it takes whatever message was passed out and sends it to Twitter.
-
1:09
There's also an LED light bulb that's here and you pass in an array of colors.
-
1:14
It's using this var args pattern, so what happens is an array will come in here, and
-
1:19
then we're going to use a Java 8 stream to collect and
-
1:23
make it comma-separated, basically.
-
1:26
More in the teachers notes on that if you're interested.
-
1:29
And finally, we have one of these huge screens that gets fans all worked up,
-
1:33
called a MegaTron.
-
1:35
And basically,
-
1:36
whatever you pass in, it says, Let's hear it for whatever was passed in.
-
1:39
Yeah, MegaTron.
-
1:41
Such a funny name for that, that that stuck, MegaTron.
-
1:45
So, anyway, the method here just roots for whatever you give it, right?
-
1:49
So, what we want, we want all these different tools to do their
-
1:53
thing when a gold medal happens, right?
-
1:55
When one of these wins are reported, we want these tools to do their thing.
-
1:59
Now it's a fairly specific to the tool type of method that we want to
-
2:03
take off, right?
-
2:04
Now we could do this by creating a base class, and
-
2:07
maybe we could mix in the adapter pattern and make them all look similar.
-
2:11
Or we could create a specific function for our use case.
-
2:16
So let's try that first.
-
2:18
So In the GoldMedalReporter, right,
-
2:21
we want to first create a way to add an observer-like function.
-
2:27
Okay, so let's do that, let's just say
-
2:32
public void, and we'll say addObserver.
-
2:38
The observer that's gonna be added here is like we just talked about,
-
2:41
it's a specific function.
-
2:43
So Java 8 introduced the concept of functional interfaces,
-
2:47
which allows you to specify an expected method signature.
-
2:51
So what we're gonna do is we're gonna use a functional interface that expects
-
2:55
a single string pattern and returns nothing.
-
3:00
So that type of interface is called a consumer, and
-
3:04
its type here that you specify is what the first parameter is.
-
3:08
So that was a string, and we'll call this observer.
-
3:21
Now we want to provide an easy way to remove these, so
-
3:24
the typical implementation in removing these is by passing in the observer.
-
3:29
But, we are going to be providing probably a lambda or
-
3:33
an anonymous function, so removing it by value is gonna be a little tricky.
-
3:38
So let's have the registering of observers need to add a key as well.
-
3:42
So we'll say String key.
-
3:47
So you'll name it and
-
3:49
then pass in the function, so it's like naming an anonymous function.
-
3:53
So we have a key and a value that we want to store.
-
3:55
That sounds pretty much like a map to me.
-
3:58
So let's add a new class up here, we'll say private map, and it's gonna be String,
-
4:03
which is the name of the function that we're going to give it, and Consumer.
-
4:08
This is the values, right?
-
4:09
So the value is going to be Consumer that we talked about.
-
4:12
It is a Java util map, and we'll call it observers.
-
4:17
And we'll say new HashMap.
-
4:20
Cool.
-
4:23
So now in our addObserver what that looks like is observers.put,
-
4:30
and we'll pass in the key and the observer.
-
4:35
Here we go.
-
4:37
So now our map is of name to function.
-
4:41
And we could very easily now remove as well.
-
4:44
Right, so we'll say public void removeObserver(String key) and
-
4:52
we'll say observers.remove, and you pass it a key.
-
5:01
And now we've got registering and unregistering of functions.
-
5:04
Now we need to notify the observer.
-
5:07
Let's make it clear, right?
-
5:10
Let's let people know that we're using the observer pattern.
-
5:13
So we'll say, notifyObservers.
-
5:17
And that's gonna take the country, right?
-
5:19
That's the string that we wanna pass in.
-
5:20
We're gonna pass in a country.
-
5:23
And all right, so we have a map.
-
5:26
And the values of the map are functions, right?
-
5:29
So observers.values.
-
5:33
And for each of those, so we'll get back a function.
-
5:39
And we want to call the method that was passed in, and
-
5:44
for a consumer, that's called accept, right.
-
5:48
And the reason why it's called accept is because it accepts the value that
-
5:52
was passed in, which in our case is gonna be country.
-
5:59
So in our reportWin, let's just go ahead and we'll say notifyObservers,
-
6:03
and we'll also pass in the country there.
-
6:06
Cool, so again, this is gonna loop through each of the functions that were passed in,
-
6:10
for each of the functions that's going to call the function, passing it the country.
-
6:14
Awesome, so let's do the Twitter one first.
-
6:17
So let's pop back into the examples here, and we have a reporter object,
-
6:23
so I'm gonna say reporter.addObserver, and let's call this observer tweet.
-
6:30
I think that makes the most sense.
-
6:32
So we could get that key out later.
-
6:34
And now it's asking for a consumer, and remember,
-
6:36
a consumer is a method that takes a string and returns nothing.
-
6:42
So we should be able to just say country.
-
6:45
Now because this is a lambda,
-
6:47
there is only one value we don't need to parentheses.
-
6:50
We're gonna say Tweeter.tweet and let's see,
-
6:55
we'll say country, Just won the Gold!
-
7:03
#olympics.
-
7:07
And it doesn't know what Tweeter is, so there we go.
-
7:11
Let's see if we can make this a prettier.
-
7:14
Screen is pretty tiny, let's do this, too.
-
7:21
Bring that up on one line here, and we'll put a semicolon at the end.
-
7:25
Okay, awesome.
-
7:26
So we've added observer, that will take a country and then call the tweet.
-
7:30
So let's do the next one.
-
7:32
Let's do the Megatron.
-
7:33
So the key is definitely gonna be megatron,
-
7:39
addObserver megatron.
-
7:43
And basically all we want to do, remember, this one just cheers for
-
7:47
whatever was passed in.
-
7:48
Basically, all we want to do is just pass in country to this method, right?
-
7:51
So because the method signature of that display method is actually a consumer,
-
7:56
right, it's actually the same.
-
7:59
A method that returns nothing and
-
8:01
accepts the string, we can just use the method reference, right?
-
8:04
So if I do megaTron:: that says,
-
8:08
I'm talking about a specific method, and the method is display.
-
8:13
So what that will do is it will, when it's observed,
-
8:16
it will pass the value into this instance.
-
8:19
Pretty cool, right?
-
8:22
Okay, and finally let's go ahead and
-
8:25
add an observer for our lights, LED light.
-
8:30
So, it's gonna take a country.
-
8:34
And we have a lights variable here.
-
8:36
So I wanna say light.flashColors.
-
8:40
And we need to access another method that's outside of this,
-
8:45
but that's okay, right?
-
8:46
We can call methods from inside of a lambda, so
-
8:48
we'll call colorsByCountry.get country,
-
8:54
and we'll hope that whatever is passed matches.
-
8:57
Right now it's only USA and Brazil.
-
9:00
Other countries do matter, I just didn't take the time to fill that out.
-
9:03
Just so you know, everybody, you matter.
-
9:07
And I just wanted to point out that these methods could be as complicated
-
9:10
as we need.
-
9:11
But most of the time, they would probably end up looking a lot like this, right?
-
9:14
They're pretty small little methods.
-
9:16
No new classes, very light interface, and
-
9:19
we did a good job of conveying that these are in fact observers, right.
-
9:23
We have all this addObserver language.
-
9:25
Let's go ahead and let's run this.
-
9:28
So I'm gonna click this Run 'Example.main()', and boom,
-
9:33
the gold medal has been awarded to the USA.
-
9:35
Let's hear it for the USA.
-
9:36
USA won the gold, #olympics, flashing red, white and blue.
-
9:40
Awesome, right?
-
9:41
We just went for the gold and we won.
-
9:43
So keep your eye out for
-
9:45
more patterns being applied in this more declarative style.
-
9:48
Do remember that these functions are closures, right?
-
9:51
So any value that's put in here will be captured, will be closed over.
-
9:57
So this approach, as well as the last one, will keep objects alive and
-
10:01
safe from garbage collectors.
-
10:04
So it's very possible to cause a memory leak if you aren't careful,
-
10:07
of removing observers when they're no longer needed.
-
10:10
So what do you think?
-
10:11
Pretty quick to implement, isn't it?
-
10:13
So now that you've seen the evolution of this pattern over time,
-
10:16
I hope you've got a really solid understanding of why you should use it,
-
10:20
as well as how to make the magic happen.
You need to sign up for Treehouse in order to download course files.
Sign up