Head First Design Patterns Review & Overview

"Head First Design Patterns" by Eric Freeman & Elisabeth Freeman with Kathy Sierra & Bert Bates, is a great programming book on the topic of 'design patterns'.  A design pattern being, "a solution to a problem in a context."  With the 'context' being a "recurring situation."  This, and other 'Head First' books, are different to other teaching books, in that they incorporate scientifically known methodologies for textbook learning. The main difference in the learnability is that other books focus on 'repetition' in order for you to remember, while on the other hand these "Head First" books focus on "anything that increases brain activity, especially different types of brain activity."  Doing this by incorporating such techniques as; pictures, redundancy in different ways, unexpected situations, emotional content whatsoever, conversational style, incorporating activities, using both sides of your brain, and many more.

 

This blog will not be a tutorial of any sort, but more of a review and overview.

 

Starting with the first chapter it covers the first design principle you're likely to come across, the 'Strategy Pattern.' The following is the formal definition:

 

Strategy Pattern: Defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

 

To me, I remember it by thinking of it as the use of a composed object that you will use polymorphically in order to change the strategy of the class. I think of it as 'composed inheritance.' I like this pattern because it lets me adapt to changes more easily. I can strategize how I want my classes to behave.

 

This section also highlighted a handful of 'design principles.' First, was simply 'Encapsulate what varies', second 'favor composition over inheritance', and third 'program to interfaces, not implementations'. These principles are easy ways to instill good programming practice in a succinct fashion.

 

 

 

The next design pattern covered is the 'Observer Pattern.' The following is the formal definition:

 

Observer Pattern: Defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically.

 

It basically lets objects (Observers) sign up to do something when an event happens upon another object (The Subject). An analogous way to think of it is like a magazine subscription. There are many subscribers (Observers) signed up to acquire magazines. Then when the publisher (The Subject) is ready to send out its product it merely looks up all its subscribers and sends it to them. The subscribers then do something in response to the arrival of their item.

 

I like this pattern because it allows me to link actions in other classes in response to the given observed class when the observed class enacts some event.

 

This section highlighted a single design principle. "Strive for loosely coupled designs between objects that interact." Loosely coupled designs allow us to build flexible OO systems that can handle change because they minimize the inter-dependency between objects. When two objects are loosely coupled, they can interact, but have very little knowledge of each other. The Observer Pattern provides an object design where subjects & observers are loosely coupled. Changes to either the subject or observer will not affect the other.

 

 

The next design pattern is the 'Decorator.' The following is the formal definition:

 

Decorator Pattern: Attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to sub-classing for extending functionality

 

You'll be able to give your (or someone else's) objects new responsibilities without making any code changes in the underlying classes--attaching additional responsibilities to an object dynamically. It provides a flexible alternative to subclassing for extending functionality. It basically lets you add behavior to a class by wrapping said objects in a decorator which jumps into the middle of an interface method in the wrapped object providing additional features.

 

I like this pattern because it allows additional behavior to be augmented onto a given class.

 

Another design principle was introduced in this section, "Classes should be open for extension, but closed for modification." aka the "open-closed principle." Strive to design systems so that closed parts are isolated from the new extensions. The Decorator pattern provides this by composing an original class within a new interface and overloading a given method which adds behavior as it augments previous decorators.

 

 

The next design pattern, or patterns, offer two implementations of the same idea. That of a 'factory'. All factory patterns encapsulate object creation. It decouples object creation from the rest of your code. The following is the formal definition for the first factory pattern:

 

The Factory Method Pattern: defines an interface for creating an object, but lets subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

 

Basically with a 'Factory Method' pattern, an abstract class has an abstract method which in subclasses is implemented as a concrete creator. Each subclass implements its own concrete creator which is the factory.

 

The second factory pattern definition follows:

 

The Abstract Factory Pattern: Provides an interface for creating families of related or dependent objects without specifying their concrete classes.

 

'Abstract Factory' has a polymorphic composed object that handles the concrete creations. This composition allows families of objects to be created through a given polymorphic assignment with the composed object.

 

A main difference between these two factory patterns is that the 'Factory Method' pattern does it through inheritance, while 'Abstract Factory' does it through composition.

 

I like these pattern styles because it allows the decoupling of object creation from the regular flow of my code.

 

This section also incorporated another design principle. "Depend upon abstractions. Do not depend upon concrete classes." A simple but powerful concept. With abstractions we can incorporate polymorphism, which is impossible with concrete classes alone.

 

 

The next design pattern is the 'Singleton'. The following is its formal definition:

 

The Singleton Pattern: Ensures a class has only one instance, and provides a global point of access to it.

 

This is one of the simplest patterns, which pretty much just makes sure that one and only one object is created of a given type. It makes the constructor private so that instantiation is mediated by a method which can make sure that only one object is being created.

 

I like this pattern because, quite simply, it allows me to make sure I don't have multiples of an object.

 

 

The next design pattern is the 'Command' pattern. The formal definition follows:

 

The Command Pattern: Encapsulates a request as an object, thereby letting you parameterize other objects with different requests, queue or log requests, and support undoable operations.

 

Basically, an event happens on some designated object (the 'invoker') which calls upon a Command object, which handles the execution of an action (upon a 'receiver'). You can pass around this command to different invokers in order to execute a receiving objects abilities whenever needed.

 

Command encapsulates a lot of code with Strategy. The 'Invoker' is strategized with the 'Command' it chooses, calling the commands 'execute' method when it wants the command to be invoked. The 'Command' is strategized with the receiving objects method, placing this method within the commands execute method. The 'invoker' can then be any object you wish to run the "Command's" execute method within.

 

I like this pattern because I can associated actions in a given class with an action in another class.

 

 

The next design pattern if the 'Adapter' pattern. The following describes its formal definition:

 

The Adapter Pattern: Converts the interface of a class into another interface the clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.

 

Basically it converts one interface to another. You compose the object you want to 'adapt' into an interface of what you want to adapt to. Then you override the methods of the interface in order to make the adaptation to a given object.

 

I like this pattern because it allows the transformation of one object to act like an entirely different object.

 

 

The next design pattern is the 'Façade' pattern. The following is its formal definition:

 

The Façade Pattern: Provides a unified interface to a set of interfaces in a subsystem. Façade defines a higher-level interface that makes the subsystem easier to use.

 

This is another quite simple pattern. It makes an interface simpler by aggregating actions to be taken. Basically it makes a macro for controlling something.

 

I like this pattern because it allows, in programming, the equivalent of a macro.

 

The next design principle was stated as "Principle of least knowledge - talk only to your immediate friends." This helps stop the creation of a lot of dependencies between many classes, which can lead to a fragile system. A fragile system can be costly to maintain and complex for others to understand.

 

 

The next design pattern is the 'Template' pattern. The following describes its formal definition:

 

The Template Method Pattern: Defines the skeleton of an algorithm in a method, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.

 

It allows you to have a portion of code in a 'façade' template method factored out into other methods, some of which are concrete and other abstract. Different subclasses will implement their own custom code in the abstract methods thereby utilizing the template.

 

I like this pattern because it minimizes code reuse by making a template from which to begin from on various similar applications.

 

This section described the following design principle, The Hollywood Principle, "Don't call us, we'll call you." It basically just means that low-level components may be hooked into a system, but the high-level components determine when they are needed, and how. Providing a "a single chain of command." This helps stop 'dependency rot', which is when you have "high-level components depending on low-level components, depending on high-level components, depending on side-ways components, depending on low-level components, and so on."

 

 

The next design pattern covered is the 'Iterator' pattern. It's formal definition is as follows:

 

The Iterator Pattern: provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

 

It's a polymorphic way to traverse through a collection, the polymorphism being the iterator interface. You compose the collection in the interface and use it's 'hasNext()' and 'next()' methods.

 

I like this pattern because it allows polymorphic iteration through any type of collection, list, or similar construct.

 

This section has the last 'design principle' of the book. It states "A class should have only one reason to change." If code has more than one reason to change then it increases the probability the class will change in the future, and when it does, it's going to affect more than one area of your design. In a sense it over complicates your life when designing and maintaining your code.

 

This also brings up the concept of 'cohesion'. It is the measure of how closely a class or module supports a single purpose or responsibility. "High Cohesion" when the class is designed around a set of related functions, and "Low Cohesion" when it is designed around a set of unrelated functions.

 

 

The next design principle is the 'Composite' pattern. It's formal definition is the following:

 

The Composite Pattern: allows you to compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly

 

Allows a way to build structures of objects in the form of trees that contain both compositions of objects and individual objects as nodes. You can then iterate through these composites and treat both compositions and individual objects uniformly because they both implement the same interface. Since composites and nodes are treated uniformly you don't have to place a bunch of if-then-else statements in your code. They are all just treated the same.

 

I like this pattern because it simplifies the interaction with the construct of trees. With their composite branches and end leaf nodes, handling both of these constructs uniformly.

 

 

This next design pattern, the 'State' pattern, has the following formal definition:

 

The State Pattern: Allows an object to alter its behavior when its internal State changes. The object will appear to change its class.

 

Allows you to switch states of a design easily. You have a bunch of instantiated 'States', each representing a state of a given construct. They are just classes representing states, each having the same actions through an interface, but they are each customized to that given State. Then there is a 'Current State' object which gets assigned one of the previously instantiated States, letting you know which State you are currently in. Then you have the actions that can be taken, which are enacted on the current state, which just passes them on to the current states code.

 

I like this pattern because it allows the easy traversement of systems with various states that change between each other.

 

 

The following pattern, the 'Proxy' pattern, has the following formal definition:

 

The Proxy Pattern: Provides a surrogate or placeholder for another object to control access to it.

 

It's basically providing a class which will limit access to another class. It can be implemented by having the proxy, and the object the proxy is mediating for, use the same interface. This way the interface only exposes actions and attributes that you would want visible. Thereby providing a security proxy. There are other types of proxies as well. Such as; a "Remote" proxy which acts as a representative for an object across a network, a "Virtual" proxy which acts as a mediator for an object that is expensive to create, and 'Protection' proxy a proxy that controls access to an object based on access rights, among other types of proxies.

 

I like this pattern because it provides a mid-way point, a mediator, where code can handle a variety of situations as such.

 

 

The next pattern is the 'MVC (Model View Controller)' pattern, which has the following formal definition:

 

The MVC Pattern: A software architectural pattern for implementing user interfaces on computers. It divides a given software application into three interconnected parts, so as to separate internal representations of information from the ways that information is presented to or accepted from the user.

 

The main goal of MVC is to separate the code for display (the 'View'), the data model (the 'Model'), and the code for mediating between 'View' and 'Model' (the 'Controller').

 

MVC is a compound pattern, meaning it incorporates multiple design patterns:

 

Observer: Many items, such as views and controllers may sign-up for updates from the 'Model'.

 

Strategy: The 'View' may strategize with various 'Controller's to achieve different results

 

Composite: The way the GUI works is inevitably a 'Composite Pattern'

 

I like this pattern because it so easily and powerfully separates code into designated areas, yet still easily interacts between them.

 

 

This last section describes patterns in the real world. A pattern being "a solution to a problem in context." The 'context' is the situation in which a pattern applies. It should be a recurring situation instead of a onetime occurrence. The 'problem' refers to the goal you are trying to achieve in the context, but it also refers to any constraints that occur in the context. The 'solution' is what you are after--a general design that anyone can apply which resolves the goal and set of constraints.

 

This also spoke of design pattern catalogs, where patterns are organized and described for general use. These abstractions of design pattern categories classify patterns to help in designating their use and learning more about them.

 

It also states in this chapter to not necessarily make design patterns your first "go to" for problem solutions. Instead follow the K.I.S.S. acronym; 'Keep It Simple Stupid'. If something simpler will work, then use it. Although, when you expect aspects of your system may vary, it may be a good sign that a pattern is needed

 

I like patterns in general because they help handle a variety of situations that would otherwise be much more difficult to handle, if at all even possible.

 

 

This book has been well worth the time to learn its contents. I foresee in the future incorporating these patterns in a variety of situations. It was easy to read and did what it was supposed to do.  It taught me solutions to common recurring design problems. I will definitely recommend it to my friends and co-workers as I'm sure that we can all find it invaluable.

 

 

More in this category: Calculator Challenge »

Leave a comment

Make sure you enter all the required information, indicated by an asterisk (*). HTML code is not allowed.

© 2015-2016 Evan Sevy. All Rights Reserved. Designed By Evan Sevy