Design Patterns Java

Tags: Java

Discover the modern implementation of design patterns in Java

Last updated 2022-01-10 | 4.4

- Recognize and apply design patterns
- Refactor existing designs to use design patterns
- Reason about applicability and usability of design patterns

What you'll learn

Recognize and apply design patterns
Refactor existing designs to use design patterns
Reason about applicability and usability of design patterns

* Requirements

* Good understanding of Java
* Familiarity with latest Java features
* Good understanding of object-oriented design principles
* A computer with the latest JDK and (hopefully) an IDE

Description

Course Overview

This course provides a comprehensive overview of Design Patterns in Java from a practical perspective. This course in particular covers patterns with the use of:

  • The latest versions of the Java programming language

  • Use of modern programming approaches: dependency injection, reactive programming and more

  • Use of modern developer tools such as IntelliJ IDEA

  • Discussions of pattern variations and alternative approaches

This course provides an overview of all the Gang of Four (GoF) design patterns as outlined in their seminal book, together with modern-day variations, adjustments, discussions of intrinsic use of patterns in the language.

What are Design Patterns?

Design Patterns are reusable solutions to common programming problems. They were popularized with the 1994 book Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, John Vlissides, Ralph Johnson and Richard Helm (who are commonly known as a Gang of Four, hence the GoF acronym).

The original book was written using C++ and Smalltalk as examples, but since then, design patterns have been adapted to every programming language imaginable: C#, Java, PHP and even programming languages that aren't strictly object-oriented, such as JavaScript.

The appeal of design patterns is immortal: we see them in libraries, some of them are intrinsic in programming languages, and you probably use them on a daily basis even if you don't realize they are there.

What Patterns Does This Course Cover?

This course covers all the GoF design patterns. In fact, here's the full list of what is covered:

  • SOLID Design Principles: Single Responsibility Principle, Open-Closed Principle, Liskov Substitution Principle, Interface Segregation Principle and Dependency Inversion Principle

  • Creational Design Patterns: Builder, Factories (Factory Method and Abstract Factory), Prototype and Singleton

  • Structrural Design Patterns: Adapter, Bridge, Composite, Decorator, Façade, Flyweight and Proxy

  • Behavioral Design Patterns: Chain of Responsibility, Command, Interpreter, Iterator, Mediator, Memento, Null Object, Observer, State, Strategy, Template Method and Visitor

Who Is the Course For?

This course is for Java developers who want to see not just textbook examples of design patterns, but also the different variations and tricks that can be applied to implement design patterns in a modern way. For example, the use of recursive generics helps us build fluent interfaces even when inheritance is involved.

Presentation Style

This course is presented as a (very large) series of live demonstrations being done in IntelliJ IDEA and presented using the Kinetica rendering engine. Kinetica removes the visual clutter of the IDE, making you focus on code, which is rendered perfectly, whether you are watching the course on a big screen or a mobile phone. 

Most demos are single-file, so you can download the file attached to the lesson and run it in IntelliJ, Eclipse or another IDE of your choice.

This course does not use UML class diagrams; all of demos are live coding. I use IntelliJ and various Maven packages where necessary.

Who this course is for:

  • Software engineers
  • Designers
  • Architects

Course content

26 sections • 145 lectures

Introduction Preview 05:11

An overview of the different topics that we'll encounter in this course as well as some info on the way the course is organized and a few words about the instructor (that's me!)

Overview Preview 00:52

Single Responsibility Principle (SRP) Preview 11:47

The Single Responsibility Principle (SRP) states that a class should have a single reason to change (i.e., one primary responsibility). The opposite of an SRP-adhering class is an antipattern called God Object.

Open-Closed Principle (OCP) Preview 18:00

A look at the Open-Closed Principle (OCP) through the prism of the Specification pattern. Two for the price of one! :)

Liskov Substitution Principle (LSP) Preview 09:42

The Liskov Substitution Principle (LSP) suggests that you should be able to substitute a base class for a derived class. What does it mean? Watch the lesson to find out.

Interface Segregation Principle (ISP) Preview 09:08

The Interface Segregation Principle (ISP) suggests that you split interfaces into smaller interfaces so that clients don't have to implement things they don't need. Also related to the YAGNI (You Ain't Going to Need It) principle.

Dependency Inversion Principle (DIP) Preview 15:16

The Dependency Inversion Principle (DIP) states that high-level modules should not depend on low-level modules but on abstractions. I also suggests a preference for depending on abstractions (interfaces/abstract classes) over concrete implementations.

Summary Preview 02:26

Gamma Categorization Preview 03:36

A brief note about the three categories of design patterns: creational, structural and behavioral.

Overview Preview 01:43

An overview of the Builder design pattern.

Builders in Java Preview 06:18

There's at least one well-known builder in Java: the StringBuilder. But what problem does it solve, exactly?

Builder Preview 09:39

Let's implement our own builder for constructing HTML lists!

Fluent Builder Preview 02:21

Fluent interfaces allow multiple calls of a builder to be called as part of a single invocation chain.

Fluent Builder Inheritance with Recursive Generics Preview 09:25

And you thought recursive generics were just for Enum? No way! They are also useful when inheriting from classes that have fluent interfaces.

Faceted Builder Preview 09:20

Sometimes the object is complicated enough so that you need more than one builder. This lesson illustrates how several related builders can interact with one another through inheritance and a fluent interface.

Builder Coding Exercise

Summary Preview 00:57

A summary of all the things we've learned about the Builder design pattern.

Overview Preview 03:08

An overview of the Factory design pattern.

Factory Method Preview 07:51

Having a static function for making an object allows us to avoid overloading problems. We can have two factory methods with identical sets of parameter types, but different names.

Factory Preview 04:27

Let's relocate all factory methods to a separate class. We have a problem: private field are no longer accessible!

Abstract Factory Preview 13:02

The Abstract Factory design pattern allows you to create hierarchy of factories corresponding to a hierarchy of types those factories create.

Factory Coding Exercise

Summary Preview 01:05

A summary of all the thing we've learned about the Factory design patterns.

Overview Preview 01:59

An overview of the Prototype design pattern.

Don't Use Cloneable Preview 11:13

If we have Object.clone() and the Cloneable interface, why don't we just use them?

Copy Constructors Preview 02:49

How can we be explicit about the fact we are making a deep copy? From the land of C++ comes the idea of making copy constructors.

Copy Through Serialization Preview 03:56

If your object graph has 10 classes in it, making 10 copy constructors (or dedicated cloning methods) is unrealistic. But we can automate the copying process via serialization.

Prototype Coding Exercise

Summary Preview 01:08

A summary of all the things we've learned about the Prototype design pattern.

Overview Preview 02:43

A look at all the things we'll learn about the Singleton design pattern.

Basic Singleton Preview 03:09

Let's implement the simplest possible singleton!

Serialization Problems Preview 07:23

Even though a constructor is private, there are at least two ways of instantiating it. The obvious way is with the use of reflections. A less obvious ways of accidentally replicating the singleton is with the use of serialization.

Static Block Singleton Preview 03:46

If the singleton constructor can throw, you can initialize the singleton instance in a static block instead.

Laziness and Thread Safety Preview 04:55

We discuss two concerns of the Singleton: lazy instantiation and thread safety.

Inner Static Singleton Preview 02:30

Thread safety issues can be mitigated via the use of a nested class.

Enum Based Singleton Preview 07:12

A singleton that exposes itself as an enumeration instance. No problem with reflection or serialization, except... you cannot serialize field values. Also, you cannot inherit from this singleton.

Monostate Preview 03:54

The Monostate design pattern is a peculiar variation on the Singleton. It's not very practical, but can be used as a 'last resort' whenever Singleton-like behavior needs to be added without breaking existing API usage.

Multiton Preview 06:38

A multiton is a Singleton-like key-value store with (optional) lazy loading.

Testability Issues Preview 09:53

Why is the Singleton so disliked? One reason is testability. Let's take a look at how a Singleton can become problematic for testing.

Singleton in Dependency Injection Preview 06:52

The only socially acceptable way of using a Singleton is via dependency injection: either done by hand or, preferably, through the use of a Dependency Injection framework.

Singleton Coding Exercise

Summary Preview 02:15

A summary of all the things we've learned about the (not-so-scary) Singleton design pattern. This concludes our investigation of Creational design patterns!

Overview Preview 02:36

An overview of the Adapter design pattern.

Vector/Raster Demo Preview 08:42

We consider a scenario where vector objects need to be rendered in raster form... this requires an Adapter!

Adapter Caching Preview 07:53

Quite often, implementation of Adapter generate temporary objects. We can implement caching to make sure we're not regenerating them on ever instance of adapter creation.

Adapter Coding Exercise

Summary Preview 01:10

A summary of all the things we've learned about the Adapter design pattern.

Overview Preview 01:46

An overview of the things we are going to learn about the Bridge design pattern.

Bridge Preview 09:11

A demonstration of vector/raster rendering with the Bridge design pattern using both manual instantiation as well as automation using Google Guice.

Bridge Coding Exercise

Summary Preview 00:21

A summary of the things we've learned about the Bridge design pattern.

Overview Preview 01:36

An overview of the things we are going to learn about the Bridge design pattern.

Geometric Shapes Preview 07:54

We illustrate an implementation of a Composite design pattern with an object that can (optionally) contain child objects.

Neural Networks Preview 09:07

A slightly more complicated demo where we get a scalar object to behave as an Iterable<> and also implement a default interface method!

Composite Coding Exercise

Summary Preview 01:10

A summary of all the things we've learned about the Composite design pattern.

Overview Preview 01:32

An overview of the Decorator design pattern.

String Decorator Preview 04:45

One well-known final class is String. So if we want to give additional behaviors, we need to introduce our own String-like class and then delegate the members. Luckily, IntelliJ IDEA helps here!

Dynamic Decorator Composition Preview 07:59

Let's build a set of decorators for geometric shapes. These decorators are all composable, so you can mix and match!

Static Decorator Composition Preview 07:23

If you want to predefine the composition of decorated types at compile-time, you can do it with Java generics, but you'll have to jump through hoops due to type erasure.

Adapter-Decorator Preview 08:15

A look at a hybrid of two patterns, the Adapter and the Decorator.

Decorator Coding Exercise

Summary Preview 01:25

A summary of the things we've learned about the Decorator design pattern.

Overview Preview 03:08

An overview of the Facade pattern.

Façade Preview 09:22

Financial trading systems often need large monitoring consoles that display aggregated data across multiple markets and bots. A typical text console is a complicated beast, but we can provide extra APIs to make it more palatable.

Summary Preview 01:25

A summary of what we've learned about the Facade design pattern. And yeah, no exercise in this section of the course. Sorry. What can I say, this is one of the more boring/obvious patterns. Write a Facade for your own system instead!

Overview Preview 02:21

A look at the Flyweight design pattern.

Repeating User Names Preview 06:18

Imagine an online game with lots of players with similar names. Do you really want to repeat the string "Smith" a thousand times? I don't think so.

Text Formatting Preview 10:19

Another implementation of Flyweight - this time, to save some memory when formatting text!

Flyweight Coding Exercise

Summary Preview 01:38

A summary of the things we've learned about the Flyweight design pattern.

Overview Preview 02:07

An overview of the Proxy design pattern.

Protection Proxy Preview 04:26

A protection proxy controls access to a particular resource or, in other words, performs some sort of checks or validation before allowing or disallowing the underlying operation.

Property Proxy Preview 06:35

Field assignments are difficult to intercept and control. What we can do is replace each field with a corresponding Property<> class that has getters and setters as methods, and interception can happen in those methods.

Dynamic Proxy for Logging Preview 09:37

Dynamic proxies are proxies constructed at runtime. Here we build a dynamic proxy for recording the number of times each object's method was called.

Proxy vs. Decorator Preview 01:18

What is the difference between a Proxy and a Decorator?

Proxy Coding Exercise

Summary Preview 00:46

A summary of the things we've learned about the Proxy design pattern.

Overview Preview 03:33

An overview of the Chain of Responsibility design pattern.

Method Chain Preview 11:06

The simplest implementation of a Chain of Responsibility involves calling a chain of handle() methods.

Command Query Separation Preview 01:28

An explanation of the concept of Command Query Separation (CQS).

Broker Chain Preview 14:10

Let's take a look at a much more sophisticated example of CoR, combining also the Observer and Mediator design patterns.

Chain of Responsibility Coding Exercise

Summary Preview 00:58

A summary of the things we've learned about the Chain of Responsibility design pattern.

Overview Preview 02:11

An overview of the Command design pattern.

Command Preview 07:09

Let's take a look at how to implement the Command pattern!

Undo Operations Preview 05:30

We can both apply and undo commands. However, it's not that easy, especially if several operations must succeed or fail together.

Command Coding Exercise

Summary Preview 01:09

A summary of the things we've learned about the Command design pattern.

Overview Preview 03:15

An overview of the Interpreter design pattern.

Handmade Interpreter: Lexing Preview 07:38

In the first part of our handmade interpreter, we build the lexing algorithm that splits textual input into a sequence of tokens.

Handmade Interpreter: Parsing Preview 09:12

In the second part of our handmade interpreter, we transform the sequence of tokens we got in the lexing stage into proper object-oriented structures.

ANTLR Preview 02:44

A well-known parser construction framework.

Interpreter Coding Exercise

Summary Preview 01:03

A summary of the things we've learned about the Interpreter design pattern. Now go study Compiler Theory!

Overview Preview 01:34

An overview of the Iterator design pattern.

Tree Traversal Preview 12:07

We construct a simple binary tree and show how one can traverse it using different iterators.

Array-Backed Properties Preview 09:56

An innovative technique that allows us to 'group' fields and treat them in aggregate fashion.

Iterator Coding Exercise

Summary Preview 01:12

A summary of the things we've learned about the Iterator design pattern.

Overview Preview 01:13

An overview of the Mediator design pattern.

Chat Room Preview 10:00

In this demo we construct a classic illustration of the Mediator design pattern - a chat room.

Reactive Extensions Event Broker Preview 07:03

An event broker is a more sophisticated kind of mediator. But we've built one before. Let's build another one, this time with the use of Reactive Extensions.

Mediator Coding Exercise

Summary Preview 01:16

A summary of the things we've learned about the Mediator design pattern.

Overview Preview 01:41

An overview of the Memento design pattern.

Memento Preview 07:22

Let's implement the Memento design pattern!

Memento for Interop Preview 03:45

Interop is easy when you need to call top-level C functions. But C++ classes cannot be used directly in Java. So what do you do? One option is to use, you guessed it, memento objects.

Memento Coding Exercise

Summary Preview 01:08

A summary of the things we've learned about the Memento design pattern.

Overview Preview 02:05

An overview of the Null Object design pattern.

Null Object Preview 04:30

Implementing a Null Object is very easy, provided the API of the underlying object is simple. So let's do it!

Dynamic Null Object Preview 07:28

A runtime-constructed null object based on Java's dynamic proxies.

Null Object Coding Exercise

Summary Preview 01:45

A summary of the things we've learned about the Null Object design pattern.

Overview Preview 01:24

An overview of the Observer design pattern.

Observer and Observable Preview 08:26

One approach to the Observer is to implement Observer<T>/Observable<T> interfaces so that's what we are going to begin with.

An Event Class Preview 09:31

Having explicit observable interfaces is too rigid an approach; how about we instead define an Event<T> class and just stick it everywhere?

The Problem with Dependent Properties Preview 02:30

Property notifications are nice... but what about read-only properties? Houston, we have a problem!

Observable Coding Exercise

Summary Preview 01:03

A summary of the things we've learned about the Observer design pattern

Overview Preview 03:08

An overview of the State design pattern.

Classic Implementation Preview 07:34

The 'classic' implementation of the State pattern is bizarre, and shown here only for illustrative purposes.

Handmade State Machine Preview 09:37

Let's make a state machine by hand. Not that difficult, actually.

Spring Statemachine Preview 10:29

Why roll your own when you can use a commercial-grade state machine library?

State Coding Exercise

Summary Preview 01:01

A summary of the things we've learned about the State design pattern.

Overview Preview 01:50

An overview of the Strategy design pattern.

Dynamic Strategy Preview 10:04

Let's implement the Strategy design pattern! The default approach is to build a dynamic strategy that can be arbitrarily replaced at runtime. Also works well with dependency injection!

Static Strategy Preview 04:50

Statically baking in the type of strategy into the type that uses the strategy is also possible, but sadly requires jumping through hoops thanks to Java's type erasure.

Strategy Coding Exercise

Summary Preview 00:26

A summary of the things we've learned about the Strategy design pattern.

Overview Preview 01:29

An overview of the Template Method design pattern.

Template Method Preview 06:28

We implement Template Method. Unlike Strategy, the Template Method is a concrete method in an abstract base class that you're meant to inherit from.

Template Method Coding Exercise

Summary Preview 00:45

A summary of the things we've learned about the Template Method design pattern.

Overview Preview 02:47

An overview of the Visitor design pattern.

Intrusive Visitor Preview 05:04

An intrusive visitor is possible through modification of existing code, a clear violation of OCP.

Reflective Visitor Preview 06:02

A reflective visitor uses type information to figure out which type to dispatch on.

Classic Visitor (Double Dispatch) Preview 09:33

A look at the classic double-dispatch visitor.

Acyclic Visitor Preview 09:38

An alternative approach to Visitor implementation.

Visitor Coding Exercise

Summary Preview 01:17

A summary of the things we've learned about the Visitor design pattern.

End of Course Preview 00:48

We've reached the end of the course. Thanks for being here! Time to say goodbye... hopefully not for long though.

Bonus Lecture: Other Courses at a Discount Preview 00:21

Some discounted links to my other courses.