• 4 hours
  • Easy

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 2/18/22

Manage Objects With Behavioral Design Patterns

What Are Behavioral Design Patterns?

If you’ve ever been to a major airport, you’ve seen many planes taking off and landing. How can all of this happen sensibly? One approach would be for every pilot to talk to every other pilot and have them coordinate among themselves who was taking off and landing, which won’t work with more than a half-dozen aircraft.

There is a behavioral pattern that solves this problem. It’s called air traffic control. There is one central place that is responsible for the coordination of all the other objects. Rather than pilots talking to each other, they talk to one central controller. The controller then sends out commands to all of the aircraft. In software, this central controller pattern is called a mediator.

Control tower and airplane
One place of control

Similarly, you often have complicated communication between objects. The behavioral patterns provide ways for objects to communicate in sensible and systematic ways.

What is the Observer Pattern?

In many situations, you have an object that has state information in it, that other objects need to be aware of. When that state information changes, all those other objects need to be informed. You use this pattern all the time when watching TV or listening to the radio.

Have you ever walked into a room, saw the TV, thought “This looks interesting,” and started watching? The TV broadcasts without having to change the way it shows the program because one more person is in the room. Eventually you lose interest and leave. Again, the TV does nothing special because you left. It’s still sending the program out to the room.

That’s the idea behind the observer pattern. Interested viewers can come and go, but the object sending out the information doesn’t have to change depending on the number of watchers.

Let’s say we had many people wanting to watch our game and on their own monitor. We would want to be able to add new view objects at any time. (In our system, we’ll add multiple viewers, but for simplicity, they’ll all be on the same screen.) We can add multiple GameViewable objects as observers by adding a new button to create them at will:

        JButton btnAddWindow = new JButton("Add Window");
        addCenteredComponent (btnAddWindow, contentPane);
        btnAddWindow.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                GameSwing game = new GameSwing();
                game.createAndShowGUI();
                gc.addViewable(game);
            }
        });

Since we used the composite pattern in the last chapter, a collection of views and a single view look the same to the controller. So no need to change any code in the controller! Now, if you click that button, you'll see new views pop up on your desktop, showing the current state of the game. And they'll all update at the same time as well.

We'll do this together! But before we do, I need to define two terms which I use in the video:

  • Threads: a thread is like a path that the tasks of your program execute on.  Each program you've worked on has a main thread, and tasks run sequentially on this thread, a little like cars on a one-lane road. Programs can use multiple threads, just like we can build multi-lane highways.

  • Thread-safe:  there's lots that goes into this topic, but in our context, we just mean making sure threads don't interfere with one another.  

Ok, let's jump in:

You can use this pattern whenever you have information that needs to be radiated out to multiple objects that care about that information. For example, you may need to send an email or a text, write to a log, and update a screen because something changed in your application. Each of the action objects (email, text, log, screen) can be told to do something by adhering to this pattern.

What is the Strategy Pattern?

In its simplest form, the strategy pattern is well-defined polymorphism. When you have a family of algorithms, you can encapsulate each one into a class that implements a common interface. 

An example is how a steak is cooked at a restaurant. Each approach, from rare to well done, does fundamentally the same thing. The chef puts the steak on the grill for a certain amount of time, flips it onto the other side, and cooks it some more. They then test for doneness. The algorithm is selected per person and then executed.

interface PrepareSteak {
    public void cook(Steak);
};

class RareSteak implements PrepareSteak {
    public void cook(Steak) {
        /* that's long enough */
    }
};
class MediumRare implements PrepareSteak {
    public void cook(Steak) {
        /* make sure it's perfect */
    }
};
class Medium implements PrepareSteak {
    public void cook(Steak) {
        /* keep it on grill a little too long*/
    }
};
class WellDoneSteak implements PrepareSteak {
    public void cook(Steak) {
        /* forget about it, come back later */
    }
};

So in the above example, when someone orders a steak, you create the corresponding object based on their order (Rare, MediumRare, Medium, or WellDone), but the method called is always the same:  cook().

This pattern uses the open/closed principle. It allows for the creation of different implementations as needed, while the caller of the strategy objects never needs to change. Use this pattern when looking to provide that extra flexibility of picking a different approach without rewriting other parts of your code.

What is the State Pattern?

In Java, you can’t dynamically add or modify methods to an object after it’s been created. But there are times when you want an object to behave differently as its state changes. One approach would be to add lots of ifs and switch statements. But that ends up with a mess of a design.

Instead, you could add a new hierarchy of classes that encapsulate those different behaviors. The object the client is using then changes the back-end object as state changes, which is the state pattern. 

For example, I ask my son to get me a soda out of the fridge. Rather than doing it himself, he yells to his sister, who is in the kitchen. She selects one she knows I like, takes it out of the fridge, and tosses him the soda. My son then hands me a vanilla-orange cola.

The next day, I again ask my son to get me a soda. This time a friend is in the kitchen. He yells to his friend who has no idea what I like, grabs a random one, and tosses it to my son. My son hands me a diet root beer. Yuck.

From my perspective, my son is behaving differently (and not just in a teenager way). Yesterday, I got what I liked. Today, I did not. Yet my son did not change.

class Son implements Person {
    private Person personInKitchen;

    public void setPersonInKitchen(Person p) {
        personInKitchen = p;
    }

    public Soda getDadASoda() {
        return personInKitchen.getSodaFromFridge();
    }
    
    public Soda getSodaFromFridge() {
        return searchForGingerAle();
    }
};

class Daughter implements Person {
    public Soda getSodaFromFridge() {
        return searchForVanillaOrange();
    }
};

class SonsFriend implements Person {
    public Soda getSodaFromFridge() {
        return grabWhateverIFindFirst();
    }
};

So in the code above, calling Son's  getDadASoda()  will in turn call the  getSodaFromFridge()  on whatever object happens to be held by the personInKitchen variable. Since that value can change, different objects implement the  getSodaFromFridge()  differently. But I'm always calling my son's  getDadASoda()  method.

Let's Recap! 

  • The observer pattern allows a state change in one object to be acted upon by many dependencies.

  • The strategy pattern allows for individual algorithms to be chosen for specific situations.

  • The state pattern allows for system behavior to vary depending on the current situation.

Now, that you've learned all this, let's recap the course! 

Example of certificate of achievement
Example of certificate of achievement