Java Design Patterns: Proven Solutions to Common Problems

Java Design Patterns: Proven Solutions to Common Problems

Design patterns have two major benefits. First, they provide proven solutions to common development issues. Each solution facilitates the development of highly cohesive modules with minimal coupling. Design patterns make the overall system easier to understand and maintain. Second, they make communication between developers and designers more efficient.

In general, patterns have four essential elements.

The pattern name is a handle developers can use to describe — in a word or two — a design problem, its consequences and its solutions. Naming a pattern immediately increases developers’ design vocabulary, allowing them to design at a higher level of abstraction. Having a vocabulary for patterns also makes it easier to think about designs and to communicate them and their trade-offs to others. However, finding good names is one of the hardest parts of developing the design pattern catalog.

The problem defines the design problem and its context, and describes when to apply the pattern to it. It might describe specific design problems such as how to represent algorithms as objects. It might describe class or object structures that are symptomatic of an inflexible design. Sometimes the problem will include a list of conditions that must be met before it makes sense to apply the pattern.

The solution defines the elements that make up the design: their relationships, responsibilities, and collaborations. The solution doesn’t describe a particular concrete design or implementation, because a pattern is like a template that can be applied in many different situations. Instead, the pattern provides an abstract description of a design problem and how a general arrangement of elements (classes and objects in this case) solves it.

The consequences are the results and trade-offs of applying the pattern. Though consequences are often unvoiced when developers describe design decisions, they are critical for evaluating design alternatives and for understanding the costs and benefits of applying the pattern. The consequences for software often concern space and time trade-offs. They may address language and implementation issues as well. Because reuse is often a factor in object-oriented design, the consequences of a pattern include its impact on a system’s flexibility, extensibility, or portability. Listing these consequences explicitly helps you understand and evaluate them.

Table 1 lists the names and descriptions of a general design pattern template.

Name Description
Pattern name and classification A conceptual handle and category for the pattern
Intent What problem does the pattern address?
Also known as Other common names for the pattern
Motivation A scenario that illustrates the problem
Applicability In what situation can the pattern be used?
Structure Diagram using the Object Modeling Technique (OMT)
Participants Class and objects in design
Collaborations How classes and objects in the design collaborate
Consequences What objectives does the pattern achieve? What are the tradeoffs?
Implementation Implementation details to consider, language-specific issues
Sample code Sample code in Java and C++
Known uses Examples from the real world
Related patterns Comparison and discussion of related patterns
Table 1. General Design Pattern Template Name and Description

Table 2 lists the names and descriptions of a Java-specific design pattern template.

Name Description
Pattern name The name and a reference to where it was first described
Synopsis A very short description of the pattern
Context A description of the problem the pattern is intended to solve
Forces A description of the considerations that led to the solution
Solution A description of the general solution
Consequences Implications of using the pattern
Implementation Implementation details to consider
Java API usage An example from the Java APO (when available)
Code example A code example in the Java language
Related patterns A list of related patterns
Table 2. Java Design Pattern Template Name and Description

The Structure of Java Design Patterns

Design patterns vary in their level of abstraction. There are many design patterns, so it helps to organize them. The sections to follow classify design patterns so that developers can refer to the appropriate patterns. Through this classification, it’s easy to identify as well as incorporate new patterns.

In 1995, software professionals Eric Gamma, Richard Helm, Ralph Johnson and John Vlissides (also known as the Gang of Four or simply GoF) published a book titled Design Patterns. This book is considered the bible or “Gita” of design patterns to the software community at large and it has been very influential in the evolution of design patterns.

Design Patterns described 23 patterns based on the experience of the authors at that time. Today, some 250 or more design patterns are used in the object-oriented world. To organize them, the GoF established three design pattern categories:

  • Creational patterns
  • Structural patterns
  • Behavioral patterns

A creational pattern prescribes the way that objects are created. These patterns are used when a decision must be made at the time a class is instantiated. Typically, the details of the classes that are instantiated — what exactly they are, how and when they are created, and so on — are encapsulated by an abstract superclass and hidden from the client class, which knows only about the abstract class or the interface it implements. The specific type of the concrete class is typically unknown to the client class.

Structural patterns prescribe the organization of classes and objects. These patterns are concerned with how classes inherit from each other or how they are composed from other classes. Common structure patterns include adaptor, proxy and decorator patterns. These patterns are similar in that they introduce a level of indirection between a client class and the class it wants to use. Their intents are different, however.

The adaptor patterns uses indirection to modify the interface of a class to make it easier for a client class to use. The decorator pattern uses indirection to add behavior to a class, without unduly affecting the client class. The proxy pattern uses indirection to transparently provide a stand-in for another class.

Behavioral patterns prescribe the way objects interact with each other. They help make complex behavior manageable by specifying the responsibilities of objects and the ways they communicate with each other.

I further categorize design patterns using two criteria: Scope and Purpose. Scope specifies whether a pattern applies primarily to a class or its objects. Class patterns deal with the relationship between classes and their subclasses. Relationships are initiated through inheritance, so they are fixed at compile time. Objects deal with object relationships, which can change at run time. Almost all patterns use inheritance, so those patterns focus on pure class patterns — patterns I labeled under class.

Purpose explains what a pattern does. Creational patterns concern the process of object creation. Structural patterns deal with the composition of classes or objects. Behavioral patterns characterize the way in which a class or object interacts and is distributed. See Figure 1 for a table of design pattern structures.

Source: Design Patterns: Elements of Reusable Object-Oriented Software

There are other ways to organize patterns. Some patterns result in similar designs even though they have different intents. You can also pass reference to other patterns to meet your requirements. Figure 2 shows design patterns’ relationship with each other.

Source: Design Patterns: Elements of Reusable Object-Oriented Software

How Design Patterns Solve Your Problems

Design patterns exist to capture best practices and propagate solutions to commonly recurring problems. The solution lies in establishing the structure and responsibilities of the individual classes and objects that make up the pattern. The main point, however, is that patterns help to identify and isolate system-level variability so the software can evolve over time without adversely affecting the underlying design structure.

The fundamental goals of creating good object-oriented designs are:

  • Encapsulate system variability
  • Favor composition over inheritance
  • Design an interface

How to Select the Right Design Pattern

When a developer decides to use a design pattern to overcome an existing issue, he or she has to choose the kind of design pattern that will fulfill this requirement. The first step is to identify which type of design pattern — creational, structural or behavioral — is going to work well for the problem?

  • If you are trying to separate the process of object construction then use creational design patterns such as the singleton, factory, abstract factory and builder patterns.
  • If you are trying to interface to a sub-system, connect to an interface your system doesn’t support, or provide a flexible storage structure for adding and manipulating objects, then use structural design patterns such as the bridge, composite and façade patterns.
  • If you are trying to access objects, perform operations or interact with operations, use behavioral patterns such as the command, iterator, observer, strategy and visitor patterns.

Now that you have determined which category your problem exists in and you have identified the principle problem you are trying to address, you can begin searching for a pattern that is designed to match your intention.

If you have articulated your intention correctly and cannot find a pattern to match, don’t fret. A design pattern may not be your solution. Design patterns address problems that occur over and over again so that the solutions they offer can be replicated. Your problem may not occur over repeatedly and thus does not have a repeatable solution.

In three upcoming articles, I will go through each design pattern category in detail, including definition, benefits, usability and examples.

Stay tuned.

Share the Post:
Heading photo, Metadata.

What is Metadata?

What is metadata? Well, It’s an odd concept to wrap your head around. Metadata is essentially the secondary layer of data that tracks details about the “regular” data. The regular

XDR solutions

The Benefits of Using XDR Solutions

Cybercriminals constantly adapt their strategies, developing newer, more powerful, and intelligent ways to attack your network. Since security professionals must innovate as well, more conventional endpoint detection solutions have evolved

AI is revolutionizing fraud detection

How AI is Revolutionizing Fraud Detection

Artificial intelligence – commonly known as AI – means a form of technology with multiple uses. As a result, it has become extremely valuable to a number of businesses across

AI innovation

Companies Leading AI Innovation in 2023

Artificial intelligence (AI) has been transforming industries and revolutionizing business operations. AI’s potential to enhance efficiency and productivity has become crucial to many businesses. As we move into 2023, several

data fivetran pricing

Fivetran Pricing Explained

One of the biggest trends of the 21st century is the massive surge in analytics. Analytics is the process of utilizing data to drive future decision-making. With so much of

kubernetes logging

Kubernetes Logging: What You Need to Know

Kubernetes from Google is one of the most popular open-source and free container management solutions made to make managing and deploying applications easier. It has a solid architecture that makes

ransomware cyber attack

Why Is Ransomware Such a Major Threat?

One of the most significant cyber threats faced by modern organizations is a ransomware attack. Ransomware attacks have grown in both sophistication and frequency over the past few years, forcing