Hi everyone! In the last lesson we talked about chaining
constructors to give ourselves more options for creating instances of our classes. While chaining constructors helped us in some
ways, it introduced a problem where we needed a specific order to create our instance, so
in this lesson I want to show you another technique for creating instances in Java using
the builder pattern. We'll also discuss a bit about what patterns
are, and some good techniques for designing your class builders. That's coming up. First, what are design patterns? We'll cover design patterns in depth later
in another series, but for now the quick 60 second version is patterns are a standard
way of addressing common programming problems with an identified solution. The solution is based on the experience of
other developers before us, and is usually recognized a good solution to a known common
problem. The beauty is, when we say builder pattern,
everyone should know we're talking about a specific solution and they should already
have a good idea for how it works. Patterns are a common language we use to communicate
with other programmers. This makes it easier to talk to others about
how a section of our code functions. What is the builder pattern? So what does the builder pattern do? The builder pattern is a pattern that allows
us to separate the construction of a more complex class, from the representation of
the class. Basically that means we're creating a class
who's sole purpose in life is to create the class we want. Imagine we're asking someone to make a PC
for us. We would tell them the amount of RAM to use,
the hard drive size, the CPU speed, and so on. The person building our computer would take
our list of specifications, and turn that into a computer to hand back to us. The builder would also tell us when we've
asked for something that can't be built. Like if we specify a SCSI hard drive, and
a SATA controller. That's how it would work in real life. Here's how it works in software. We create a class that contains all the state
variables we need to set to create a functioning object. We have a setter for each of these values. You'll notice we drop the "set" word from
the method name. This is a departure from how we normally do
getters and setters. It's because the builder uses the Fluent Interface
idiom. The Fluent Interface idiom just makes the
code more readable when you're using the class. The interesting part is the setter returns
a builder object holding the value, and any other previously set values. This allows us to chain our calls together. When we're done, we call the build() method
on the builder. That returns us an instance of the object
we want, with everything configured. If the builder can't build our instance, it
should error out and not create the instance. In Java the standard way of doing this is
to throw an exception. Exceptions are a longer topic we'll cover
in depth. For now we'll just throw exceptions using
this code. IllegalStateException is the exception we
throw when someone is trying to create our class in an illegal state. Exceptions are a longer topic we'll cover
in depth in a later lesson. Just know this is causing an error, and prevents
the instance from getting created. How does this help? Well for starters, order is no longer important. We can specify our attributes in any order. In our football game, we can specify the home
team, then the stadium, then the starting position, and then the away team. Or we can specify them in another order. In the end, our builder will give us a usable
instance or an error. We'd use this over chaining constructors because
we can mix around the order of our state. It also allows us to prevent object creation
in an inconsistent state. We can't create a game instance where only
one team is specified. We can't forget to position the ball on the
35 yard line. The builder will not return an instance until
it has all the information needed to create the instance in a usable state. The builder pattern would be overkill if you
have only a few attributes to set. For example, we probably would not use a builder
pattern to create an object with three attributes. Chaining is a simpler solution for simple
classes. The builder pattern is for larger, more complex
class construction. Implementing the builder pattern
Let's create a builder for our football game. We'll create the class with all the parameters
we need for the game class. If we want to give any of these attributes
default values, we'll do it in the builder. Each setter sets the value, then returns the
GameBuilder instance. Then we provide a builder method. This method first checks we have all the information
we need to build the instance. If we cannot create the instance in a useable
state, we'll throw an IllegalStateException. Finally we'll create the instance in one go,
and return the result. We will also create a single constructor for
our class that accepts the builder as a parameter. This makes sure users of our class use the
builder, one way or another. You can create an instance of your class with
this code. This calls the build() method on the builder. This is the preferred way to use the builder
pattern. Another way to do it, is to populate a builder,
and then pass that to the class. This way is less desirable, because it's harder
to read. The only reason you can do it this way is
because we need to create a single constructor for our game object. This enforces object creation through the
builder. The constructor with a builder argument should
be the only way to create your instances. This prevents sneaky developers from trying
to create instances without using the builder. We really want anyone using our class to use
the builder. In order to completely prevent instance creation
without using the builder, we need make the builder part of the class. We can define a class inside a class. So our builder would be a static class inside
our class. In this case, you'd make the constructor private. This way we can only create new instances
from the builder. There is no constructor exposed. Thanks for watching! That was a longer lesson, so if you have any
questions let me know in the comments. New lessons come out every week, so make sure
you subscribe. You don’t want to miss a video! And with that, I’ll see you in the next
tutorial!