The pattern concept | CodeGuru

The pattern concept

Bruce Eckel’s Thinking in Java Contents | Prev | Next Initially, you can think of a pattern as an especially clever and insightful way of solving a particular class of problems. That is, it looks like a lot of people have worked out all the angles of a problem and have come up with the […]

Written By
CodeGuru Staff
CodeGuru Staff
Mar 1, 2001
5 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

Initially,


you can think of a pattern as an especially clever and insightful way of


solving a particular class of problems. That is, it looks like a lot of people


have worked out all the angles of a problem and have come up with the most


general, flexible solution for it. The problem could be one you have seen and


solved before, but your solution probably didn’t have the kind of


completeness you’ll see embodied in a pattern.

Although


they’re called “design patterns,” they really aren’t


tied to the realm of design. A pattern seems to stand apart from the


traditional way of thinking about analysis, design, and implementation.


Instead, a pattern embodies a complete idea within a program, and thus it can


sometimes appear at the analysis phase or high-level design phase. This is


interesting because a pattern has a direct implementation in code and so you


might not expect it to show up before low-level design or implementation (and


in fact you might not realize that you need a particular pattern until you get


to those phases).

The


basic concept of a pattern can also be seen as the basic concept of program


design: adding a layer of

abstraction.
Whenever you abstract something you’re isolating particular details, and
one of the most compelling motivations behind this is to
separate
things that change from things that stay the same
.
Another way to put this is that once you find some part of your program
that’s likely to change for one reason or another, you’ll want to
keep those changes from propagating other changes throughout your code. Not
only does this make the code much cheaper to maintain, but it also turns out
that it is usually simpler to understand (which results in lowered costs).

Often,


the most difficult part of developing an elegant and cheap-to-maintain design


is in discovering what I call “the

vector
of change.” (Here, “vector” refers to the maximum gradient
and not a collection class.) This means finding the most important thing that
changes in your system, or put another way, discovering where your greatest
cost is. Once you discover the vector of change, you have the focal point
around which to structure your design.

So


the goal of design patterns is to isolate changes in your code. If you look at


it this way, you’ve been seeing some design patterns already in this


book. For example,

inheritance
can be thought of as a design pattern (albeit one implemented by the compiler).
It allows you to express differences in behavior (that’s the thing that
changes) in objects that all have the same interface (that’s what stays
the same).
Composition
can also be considered a pattern, since it allows you to change –
dynamically or statically – the objects that implement your class, and
thus the way that class works.

You’ve


also already seen another pattern that appears in


Design
Patterns

:


the

iterator
(Java 1.0

and 1.1 capriciously calls it the
Enumeration;
Java 1.2

collections use “iterator”
).
This hides the particular implementation of the collection as you’re
stepping through and selecting the elements one by one. The iterator allows you
to write generic code that performs an operation on all of the elements in a
sequence without regard to the way that sequence is built. Thus your generic
code can be used with any collection that can produce an iterator.

The
singleton

Possibly


the simplest design pattern is the

singleton,
which is a way to provide one and only one instance of an object. This is used
in the Java libraries, but here’s a more direct example:
//: SingletonPattern.java
// The Singleton design pattern: you can
// never instantiate more than one.
package c16;
 
// Since this isn't inherited from a Cloneable
// base class and cloneability isn't added,
// making it final prevents cloneability from
// being added in any derived classes:
final class Singleton {
  private static Singleton s = new Singleton(47);
  private int i;
  private Singleton(int x) { i = x; }
  public static Singleton getHandle() {
    return s;
  }
  public int getValue() { return i; }
  public void setValue(int x) { i = x; }
}
 
public class SingletonPattern {
  public static void main(String[] args) {
    Singleton s = Singleton.getHandle();
    System.out.println(s.getValue());
    Singleton s2 = Singleton.getHandle();
    s2.setValue(9);
    System.out.println(s.getValue());
    try {
      // Can't do this: compile-time error.
      // Singleton s3 = (Singleton)s2.clone();
    } catch(Exception e) {}
  }
} ///:~ 

The


key to creating a singleton is to prevent the client programmer from having any


way to create an object except the ways you provide. You must make all

constructors
private,
and you must

create
at least one constructor to prevent the compiler from
synthesizing
a default constructor for you (which it will create as “friendly”).

At


this point, you decide how you’re going to create your object. Here,


it’s created statically, but you can also wait until the client


programmer asks for one and create it on demand. In any case, the object should


be stored privately. You provide access through public methods. Here,


getHandle( )

produces the handle to the


Singleton

object. The rest of the interface (


getValue( )

and


setValue( )

)


is the regular class interface.

Java


also allows the creation of objects through cloning. In this example, making


the class


final

prevents cloning. Since


Singleton

is inherited directly from


Object

,


the


clone( )

method remains


protected

so it cannot be used (doing so produces a compile-time error). However, if


you’re inheriting from a class hierarchy that has already overridden


clone( )

as


public

and implemented


Cloneable

,


the way to prevent cloning is to override


clone( )

and throw a


CloneNotSupportedException

as described in Chapter 12. (You could also override


clone( )

and simply return


this

,


but that would be deceiving since the client programmer would think they were


cloning the object, but would instead still be dealing with the original.)

Note


that you aren’t restricted to creating only one object. This is also a


technique to create a limited pool of objects. In that situation, however, you


can be confronted with the problem of sharing objects in the pool. If this is


an issue, you can create a solution involving a check-out and check-in of the


shared objects.


Classifying
patterns

The


Design
Patterns

book discusses 23 different patterns, classified under three purposes (all of


which revolve around the particular aspect that can vary). The three purposes


are:

  1. Creational:
    how an object can be created. This often involves isolating the details of
    object creation so your code isn’t dependent on what types of objects
    there are and thus doesn’t have to be changed when you add a new type of
    object. The aforementioned
    Singleton
    is classified as a creational pattern, and later in this chapter you’ll
    see examples of
    Factory
    Method

    and
    Prototype.
  2. Structural:
    designing objects to satisfy particular project constraints. These work with
    the way objects are connected with other objects to ensure that changes in the
    system don’t require changes to those connections.
  3. Behavioral:
    objects that handle particular types of actions within a program. These
    encapsulate processes that you want to perform, such as interpreting a
    language, fulfilling a request, moving through a sequence (as in an iterator),
    or implementing an algorithm. This chapter contains examples of the
    Observer
    and the
    Visitor
    patterns.

The


Design
Patterns

book has a section on each of its 23 patterns along with one or more examples


for each, typically in C++ but sometimes in Smalltalk. (You’ll find that


this doesn’t matter too much since you can easily translate the concepts


from either language into Java.) This book will not repeat all the patterns


shown in


Design
Patterns

since that book stands on its own and should be studied separately. Instead,


this chapter will give some examples that should provide you with a decent feel


for what patterns are about and why they are so important.


Contents

|

Prev

|

Next
CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.