When does class start/end?
Classes begin promptly at 9:00 am, and typically end at 5:00 pm.
The Java Design Patterns Course is authored by Heinz Kabutz, the publisher of The Java Specialists' Newsletter, with contributions from one of the authors of the original "Gang-of-Four" Design...
Read MoreThe Java Design Patterns Course is authored by Heinz Kabutz, the publisher of The Java Specialists' Newsletter, with contributions from one of the authors of the original "Gang-of-Four" Design Patterns book. Design Patterns have become the standard way in which we think about object oriented software development. During this 3-day course, we study the most useful Gang-of-Four design patterns: Singleton, Factory Method, Abstract Factory, Template Method, Strategy, Iterator, Observer, Adapter, Decorator, Composite, Visitor, Command, Memento, Chain of Responsibility, State, Facade, Flyweight, Bridge and Proxy. Each design pattern is followed by practical hands-on exercises to apply what you have learned, using both UML and Java code.
Please refer to Design Pattern Course Content Details
Prior Knowledge: Participants should have a good understanding of object orientation concepts such as inheritance, encapsulation and polymorphism. Knowledge of Java is an advantage. Preparation: Read the book Head First Design Patterns. Equipment: Computers with the latest version of Sun JDK preinstalled, together with either Eclipse or IntelliJ IDEA.
Our Design Patterns Course takes a total of 21 lectures. Each pattern is followed by a short group discussion and then some hands-on exercises to apply what we have learned. The course can be delivered either as classroom or as live virtual class. The classroom training would usually be done in a three day block. Here is the typical schedule:
In the first section, we lay the foundation for the rest of the course. We talk about why patterns are important, where they come from, their general structure and give a UML refresher.
Our first stop is structural patterns, since most of us can relate to these easily.
The Proxy pattern is used in many systems to provide placeholder objects. Most programmers have seen or used this pattern. This makes it a good first pattern to study as we quickly see the benefit of using design patterns. We study various ways of creating proxies. We show how to write them by hand, how to generate them using the new Java 6 built-in compiler and how to create them as dynamic proxies. We also study different uses of proxy types. Examples are virtual, remote and protection proxies. We show how these can be created with dynamic proxies or automatically generated code.
The adapter is next. In a perfect world, this pattern would not exist. However, often interfaces do not match correctly between different parts of our system and this pattern is the glue that connects these mismatched parts. We look at the naming of this pattern, which has caused confusion in the past. Lastly we compare the structure of this pattern against the proxy.
The Facade pattern is often confused with the session facade. In fact, it is not really a design pattern. Rather, it is a necessary part of any complex design thanks to the added flexibility that patterns bring.
When you have objects arranged in a tree structure, this pattern will help you make clients simple. Clients do not need to worry whether they are speaking to a single object or a large group of objects. We explain why the interface at the top of the hierarchy seems too general, but is in fact exactly the way that it should be.
Our next set of patterns are used for algorithms and behavior. They help to reduce duplicate code and get rid of if-else and switch statements. Code becomes less complex with less duplication, leading to lower costs.
The template method is used when we have some classes which do the same thing, but a bit differently. We can replace the duplicate code with a single template method and can push the differences into primitive methods, which are contained in subclasses. We compare the template method to the strategy and show how they might be combined to produce a truly flexible design.
We use this pattern when we need to have several ways of doing the same thing. For example, we might want to sort a list using as little temporary memory as possible. Or our constraint might be CPU, in which case we would want to replace our sorting algorithm with one that performs better. We also see some of the drawbacks of using the strategy pattern by studying the AWT layout managers.
Most Java people think that they know the iterator, after all, that is how we walk through groups of objects. However, the GoF pattern has some interesting variations and options that are not available in the Java version. For example, why does it have to be the client that controls the iteration? How could we write a robust iterator in Java? This pattern has a lot more facets than most people realize.
The observer pattern is one of the most prolific ideas in object oriented designs. It helps us to decouple the components. We show how the Java observer was implemented and use this to build a simple stock price viewer, where observers can get notified when a share changes.
Creational patterns are the most tricky to get right. They are frequently abused for building systems that are non object oriented. In this section we look at the three most common creational patterns and show how they should be used.
Ask a group of novice programmers if they know any patterns and the "singleton" is the most common answer you will get, next to "factory" and "MVC". In this section we discover the real purpose of this pattern. The purpose of this pattern is to be able to substitute one singleton object for another without the clients having to know. Sadly most of the time it is used to put global variables into systems. We learn how to correctly use this pattern.
The GoF factory method pattern is used to allow subclasses to create their own instances of their own specific types. An example would be the iterator() method of the Collection interface. We give examples of how and when this should be used.
We use this pattern to manage families of objects that need to be created. An example is when we need to support GUI components for several operating systems. We show how we can use this pattern to create software that can easily be migrated to new hardware.
In the second set of behavior patterns, we learn how to decouple our designs even further with the Visitor and Command. We implement a multi-level undo and redo with the memento. We show how to build chains of implementers with the Chain of Responsibility. We end with the State Pattern that should be used whenever we have more than a couple of states in our classes.
The Visitor integrates well with the composite patterns. It provides a way to modify the methods invoked on all of the objects in the structure. Instead of hard-coding the composite method, we provide a mechanism to "visit" each class and apply class specific methods. It is a great pattern for managing collections of disparate classes.
The command pattern helps to clearly assign responsibilities, which leads to a decoupled design. We show why the typical AWT action listener is not the best way of using the pattern. We then demonstrate how we get a cleaner design when we follow the pattern structure more closely. The exercise is challenging as the first instinct is to use an object adapter, but that would lead to an inflexible design.
We learn how to use the memento pattern to store state. This allows us to do multi-level undo and redo, combined with the Command pattern. The memento is also compared to the serialization mechanism in Java.
This pattern allows us to define flexible systems where we do not need to specify at coding time which object will process a message. This is set up by configuring the chain. We look at some of the issues that happen when a message drops off the end of the chain.
The last behavioral pattern is the State pattern. Use this whenever you have more than one conditional statement in your class that changes the branch depending on some internal field. It is one of the most useful patterns to produce reliable software.
We end our course with three structural patterns that are again fairly easy to grasp. Flyweight, similarly to the Facade, is mainly used to deal with the effects of patterns - lots of little objects. We see how Bridge is used to decouple the abstraction from the implementation. Lastly we show how we can change the interface of an object dynamically with the decorator.
The flyweight is used to reduce the memory footprint of objects. It does this by changing intrinsic state to extrinsic and then sharing instances. Well factored code often causes lots of objects to be constructed. The flyweight is one of the solutions to manage this problem.
The bridge pattern helps us to define separate hierarchies for the abstractions and implementations. We learn how this relates to strategy and adapter. Bridge helps us design systems that can work with different external components, without changing the main abstraction.
The decorator is used for two main purposes. Firstly we use it to add functionality to existing objects. We call this decorating. Secondly we can take it away from objects. We call this filtering.
The course ends with a conclusion about what we have learned and where to study them further. We also look at how the patterns are all connected.
We give a number of great references where you can learn new patterns and study the subtleties of patterns further.
Lastly, we give some pointers on how to write your own patterns. This process is called discovering or inventing a pattern.