Patterns for Java and Distributed Computing

Abstract: In this project, we will take a comprehensive tour of design patterns and their use in Java programming and distributed computing. Part I introduces the concept of patterns and some related terms. Part II introduces the GoF Design patterns and briefly describes each one of these fundamental patterns, providing online resources to each. Part III explores descriptions of patterns that are available online that can teach how to design better programs using Java and Distributed Computing.


Table of Contents

Note on Navigating Section-title Hyperlinks
Wherever you see a hyperlink with the name of a section anywhere in this document, following that hyperlink will do one of two things:
  1. If you are not already inside that section, then following the link will take you to the top of that section.

  2. If you are already inside that section, following the title-link at the top of the section will take you back to the table of contents for its containing section.
Hopefully this should make it convenient to quickly navigate back and forth in this presentation.

Short Table of Contents

Detailed Table of Contents


Part I :
About Patterns

What are Patterns?
Some Pattern Definitions
Patterns Aren't Just for Design
Pattern Origins and History
Pattern Elements and Formats
Canonical Pattern Form
GoF Pattern Form
GoF Form versus Canonical Form
Much Ado about Patterns
Pattern Resources - Books
Pattern Resources - Internet


What are Patterns?

Software patterns are many things:
Trendy:
Patterns are a recent "hot-topic" in the object-oriented design world. The word pattern has become a popular buzzword surrounded by a great deal of hype (some good, and some bad).

Literary:
Patterns are a form of software engineering problem-solving documentation. They try to distill the essence of useful solutions, capturing them into a literary format that can be readily communicated, discussed and understood.

Pragmatic:
Patterns attempt to describe practical solutions to "real world" problems. They are supposedly used to describe proven practice rather than theoretical speculation.

Recurring:
One of the most essential aspects of patterns is that they repeat. The solutions they describe are used over and over by different people in different places to solve the common problems that arise in their work. People who didn't necessarily know about each other tend to independently gravitate toward the same sorts of solutions to solve their commonly recurring problems. Patterns are an attempt to name and explain these useful design structures which recur in practice!

Generative:
Some would say "generativity" is a fancy way of saying that a pattern is supposed to teach you something. The reasoning is that a pattern shouldn't just describe a problem and its solution, it is supposed to include discussion of how and why the problem is truly difficult, and how and why the solution balances all the competing concerns, constraints, trade-offs, etc., that are inherent in the problem being solved.

So a pattern is supposed to do more than simply provide some cookbook solution. It should also explain how and when to apply the solution, and show why the generated the design structure is desirable. Rather than some cookie-cutter template that is confined to a specific implementation, a pattern is supposed to explain the underlying motivation and essential workings of the solution. Then the reader can understand the experience and insight that went into that solution, and figure out how to adapt it or adjust it to their own needs in any one of an infinite number of ways.

Emergent:
Once people are able to think in terms of patterns, the patterns become conceptual building blocks in your mind that enable you to communicate about design solutions at a broader level. They can be combined and interwoven together to solve larger problems than any one standalone pattern. These larger solutions emerge indirectly from applying patterns in succession, and in combination together.


Some Pattern Definitions

A generic definition of a pattern that one might find in a dictionary is:

An abstraction from a concrete form which keeps recurring in specific, non-arbitrary contexts.

An extremely abridged version of the definition used by Christopher Alexander is:

A recurring solution to a common problem in a given context and system of forces.

These definitions don't explain the fact that a pattern is supposed to have a name (to make it easier to talk about in discussions and design) and that it has some required elements or format. A pattern is supposed to be a successfully recurring "best practice" that has proven itself in the trenches of real-world use. They are described using a literary format that tries to capture the wisdom and experience of expert designers so it can be communicated to novices. Putting all this together with the above definitions, we can say that:

A pattern is a named "nugget" of instructive insight, conveying the essence of a proven solution to a recurring problem in a given context amidst competing concerns.


Patterns Aren't Just for Design

After their initial popularity in the field of object-oriented design (OOD), software patterns began branching out into other areas. There are still design patterns that deal with software design (often object-oriented). Some have split these into categories like: architectural patterns which deal with systems-level design; design patterns which deal with interactions between individual software components or objects; and programming idioms that deal with program language-specific techniques and style.

But software patterns have spread in popularity beyond the scope of design and are being written and used for other aspects of software engineering as well. There are analysis patterns which describe reusable and recurring requirements analysis models and strategies; organization patterns which describe successful structures of organizations and projects in terms of roles, responsibilities, and interactions between people and groups; and process patterns which describe the design of software processes rather than software products.


Pattern Origins and History

The most frequently cited origin of patterns would have to be the writings of architect Christopher Alexander. Alexander coined the use of the term "pattern" to refer specifically to recurring solution-structures around 1977-1979 in two books:

Of course the documentation of best practices and handbooks for engineering and architecture was already common practice. And folks like Don Knuth had popularized ideas such as Literate programming. Many of these ideas came together in software in the late 70's and early 80's.

The application of Alexander's ideas to patterns for software design and development was apparently first performed by Kent Beck and Ward Cunningham, then at Textronix. Ward and Kent gave a presentation at the OOPSLA'87 conference that referred to Alexander's work and described some "design patterns" for GUI design in the Smalltalk programming environment.

Then, in the late 80's and early 90's, a fellow named Erich Gamma was working on his Ph.D. thesis about software architecture and object-oriented design patterns; while another fellow named James Coplien wrote a book of Advanced C++ Idioms for object-oriented design in C++.

By this time, patterns for object-oriented software design ("design patterns") had become very popular within certain elite circles of the O-O community. But it wasn't until the publication of the landmark book Design Patterns that the usefulness and popularity of patterns became widespread:

Design Patterns: Elements of Reusable Object-Oriented Software;
Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides;
Addison-Wesley, 1995

Since the publication and subsequent high praise and acceptance of this book (whose authors have been nicknamed the "Gang of Four" or just "GoF"), the popularity and publication of patterns, pattern books and conferences has skyrocketed.

Another popular patterns book which came out shortly after the GoF book is the "POSA" book (POSA is the acronym formed by the major title, the acronym for the full title is actually a palindrome, POSA-ASOP, which the authors claim was deliberate :-):

Pattern-Oriented Software Architecture: A System of Patterns (POSA)
Frank Buschmann, Regine Meunier, Hans Rohnert, Peter Sommerlad, Michael Stal;
John Wiley and Sons, 1996
Many other books have since been published, and in fact Addison-Welsey has a software patterns series of books which includes selected patterns from various patterns conferences, and another popular book on Analysis Patterns by Martin Fowler. More recently, John Vlissides published a kind of "sequel" to the GoF book entitled Pattern Hatching: Design Patterns Applied.


Pattern Elements and Formats

There are a few commonly used formats (or "forms") used to describe patterns. The two most popular formats are called GoF Form (named after the format used by the "Gang of Four" in their "Design Patterns" book) and Canonical Form, which was made popular by Jim Coplien, the POSA book, and AGCS.

Another common pattern form is called Alexandrian form, which is basically the same format used by Christopher Alexander when he wrote his book of patterns about urban architecture. There is a set of webpages at the Wiki Web (created by yours truly ;-) that describes and compares many of the more popular pattern forms. This section will simply describe the bare essentials of the two most common pattern forms.

Canonical Pattern Form

Canonical pattern format consists of the following elements or sections. Not all sections are required, and they aren't always explicitly labeled or titled as such, but they typically use the section titles shown here:

Name The name of the pattern - It should serve as a meaningful "conceptual handle" for discussion
Aliases Any other names this pattern is commonly known by in practice (optional)
Context Provides important background information for the pattern's applicability. It says how the problem occurs, and when the solution works
Problem The statement of the problem or intent of the solution
Forces Trade-offs, goals & constraints, motivating factors and concerns that any attempted solution needs to consider. Forces explain how and why the problem is difficult
Solution Describes how to construct or generate the solution The solution structure, its participants & collaborations
Examples Provides pictures and examples of the how to use and apply the pattern (optional)
Resulting
Context
Describes the end result: the benefits and consequences of applying the patterns. It shows how the forces were balanced or traded-off; any compromises the solution makes; and how the solution works out.
Rationale Describes any underlying principles or heuristics justifying the solution. It attempts to explain Tells underpinnings of why the solution works out. (optional)
Known
Uses
Cites 2-3 or more independent instances of "real world" success.
Related
Patterns
Refers to patterns which are similar to this one, or which may precede or follow the application of this particular pattern.

GoF Pattern Form

GoF pattern format consists of the following elements or sections. You can see that it shares many common characteristics with canonical pattern format, but is tailored more specifically for describing software design structures. The descriptions below are taken directly from the GoF text with slight adaptation

Name The pattern's name conveys the essence of the pattern succinctly. A good name is vital because it will become part of your design vocabulary.
Classification Categorizes the pattern into one of the following categories:
  • Creational patterns are concerned with object creation
  • Structural patterns are concerned with the composition of classes or objects
  • Behavioral patterns characterize the ways in which classes or objects interact and distribute responsibility
The GoF book uses these three categories but subsequent pattern authors have introduced additional ones.
Intent A short statement that answers the following questions: What does this design pattern do? What is its rationale or intent? What particular issue or design problem does it address?
Also
Known
As
Other well-known names for the pattern, if any.
Motivation A scenario that illustrates the design problem and how the class and object structures in the pattern solve the problem. The scenario will help you understand the more abstract description of the pattern that follows.
Structure A graphical representation of the structure of classes and objects in the patterns. Sometimes interaction diagrams are used to illustrate sequences or requests and collaborations between objects. The GoF book used OMT notation for objects and classes and Booch notation for interaction diagrams.

These days most people use UML for drawing their O-O design pattern diagrams. But since UML is a unification of OMT and Booch (and others) the diagrams in the GoF book are still mostly recognizable to those familiar with UML but not OMT or Booch notation.

Participants The classes and/or objects participating in the design pattern and their responsibilities
Collaborations How the participants collaborate to carry out their responsibilities
Consequences How does the pattern support its objectives? What are the trade-offs and results of using the pattern? What aspect of system structure does it let you vary independently.
Implementation What pitfalls, hints, or techniques should you be aware of when implementing the pattern? Are there language-specific issues?
Sample
Code
Code fragments that illustrate how you might implement the pattern in C++ or Smalltalk. At the time the GoF book came out, Java didn't exist yet (except to Sun Microsystems :-).
Known
Uses
Examples of the pattern found in real systems, preferably including at least two examples from different domains.
Related
Patterns
What design patterns are closely related to this one? What are the important differences? With which other patterns might this one be used?

GoF Form versus Canonical Form

As was stated earlier, these two pattern formats share many common characteristics. The main difference is that the canonical format places a more explicit emphasis on forces and the resolution; whereas GoF format breaks up the solution into more sections and uses more formal design diagrams along with sample code.

Clearly those sections with the same or similar names have the same meaning (e.g., Name, Aliases, Also Known As, Known Uses, Related Patterns). The "Intent" and "Problem" sections of each can be considered roughly equivalent; so can "Applicability" and "Context", as well as "Consequences" and "Resulting Context"; The "Forces" of canonical format are implied by the scenario discussed in the GoF "Motivation" section, and also partly in the "Intent." The GoF format splits the canonical "Solution" section across the sections for Structure, Participants, Collaborations, Implementation, and Sample Code.


Much Ado about Patterns

So now that we've spent all this time talking about patterns, what was it they're supposed to be good for again? In summary, software patterns help software developers because they:

However, we don't want to spread hype and myths and misconceptions; we should try be very clear about what patterns are and aren't. Software patterns are not:

So if I've given anyone the misimpression that patterns are supposed to be any of the above things, let me assure you that is not my intent. The above myths and misconceptions are an unfortunate result of excessive hype. These myths need to be dispelled. Software Patterns are:

For a far more thorough and comprehensive (and long-winded ;-) introduction to patterns terms and concepts, interested parties can surf on over to the following online "primer" that I've written:

Patterns and Software: Essential Concepts and Terminology
The above will probably tell you more than you ever wanted to know about patterns. But it's chock full of hyperlinks to patterns examples and resources. I've included just a few of them here:

Pattern Resources - Books

Pattern Resources - Internet


Part II:
The GoF Design Patterns

GoF Design Patterns Resources
Creational Design Patterns
Structural Design Patterns
Behavioral Design Patterns


Okay - 'nuff said about patterns! It's time to stop talking about them and start taking a look at some real instances of them! Unfortunately I can't actually reproduce or discuss each of them in it's full glory and detail without violating copyrights or exceeding 100 pages of text. So what I'll try to do is give an abridged description of the 23 GoF Design Patterns and see if I can related them to things we learned in this course. I'll also try to provide hyperlinks to resources about each of the patterns.

[ NOTE that all the UML diagrams depicting these patterns are included as hyperlinks instead of embedded directly into this webpage! I tried including them directly but it just takes too darn long to download almost two dozen JPEG images as part of this webpage. So please follow the hyperlinks if you want to see the diagrams. I recommend bringing them up in a separate browser window. ]

GoF Design Patterns Resources

Joshua Kerievsky, of Industrial Logic, has an outstanding GoF Design Patterns Study Guide available at his website. It doesn't explain each pattern; Rather, it suggests a particular order in which newcomers should first study these patterns, and poses some study questions to ask yourself as you read through the Design Patterns book.

Kyle Brown has created a tutorial introduction to patterns and pattern languages and also to the GoF design patterns using Java and UML. Kyle has been doing object-oriented design with patterns and Java (and before that with Smalltalk) for a very long time and is quite an expert in the field.

Mark Grand has authored a three volume set of Design Patterns in Java (with diagrams in UML). Mark is a Java expert too, but he hasn't been doing patterns for as long as Kyle has. Volume I gives Java implementations and examples of all of the GoF design patterns, as well as a couple dozen other patterns. Some of them were originally written up by other authors (like the GoF, for example), and some of them he wrote-up himself. We'll mention some of those other patterns a bit later. Right now we're focusing on the GoF patterns.

Vince Huston has a web page devoted to the GoF Design Patterns complete with descriptions and sample code for each. Most of the examples are in C++ but several Java examples are provided as well. Vince also has some links to other patterns resources at this webpage.

Alexander Ran has given a seminar on design patterns, including a session on Design Patterns in AWT that describes how various structures in the Java AWT are instances of one or more GoF design patterns.


Creational Design Patterns


Abstract Factory

INTENT: Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

Online Resources to Abstract Factory

Given a set of related abstract classes, we often need to create instances of those abstract classes from a corresponding set of concrete subclasses. Suppose I have abstract classes corresponding to a GUI Window, and a Panel, and a TextEntry field, and a ScrolledText field, and any other number of GUI widgets. If the program needs to run on multiple platforms, then I might need a platform-specific implementation for each widget. So I might have concrete classes like MSWindow, MacWindow, MotifWindow, MSPanel, MacPanel, MotifPanel, etc., for each abstract widget that I need to represent.

You want to be able to create a Window object to program with, but without having to know which concrete subclass of Window to create. Similarly, you want to be able to do the same for each widget you provide in your API.

The Java AWT needs to do this. Classes like "Panel" and "Component" are actually abstract classes, and Java has "peer components" for each class that are specific to the windowing environment in which it runs.

This is the problem that an Abstract Factory solves. Each widget has its own class hierarchy with the abstract class at the root, and the concrete platform-specific implementations as subclasses. Then you create an additional hierarchy of factory objects. The "Abstract Factory" class is at the root of this factory hierarchy. Concrete subclasses of this abstract factory would be classes like MSWidgetFactory, MacWidgetFactory, and MotifWidgetFactory.

[follow this link to see the UML diagram]

The abstract methods in the abstract factory class are used for creating and returning a particular kind of widget. So method names would be things like CreateWindow(), CreatePanel(), CreateComponent(), CreateTextField(), etc. Each concrete subclass of the AbstractFactory knows how to create widgets for its own windowing environment (see Factory Method). At run-time, I might have a single instance of an abstract factory object (see Singleton). I would figure out which concrete subclass of abstract factory to create, and then assign the result of that allocation to an AbstractFactory reference. This logic could be completely separate from the code that needs to use and create widgets.

Anyone needing to create a certain kind of widget simply calls the appropriate method of the abstract factory object. Each widget creation method returns a reference to the abstract widget type (e.g. Window or Panel) but the object that was created, and which is being referenced via the abstract widget variable is really an instance of the concrete widget type (e.g. MacWindow or MotifPanel).

Alexander Ran explains how the Java AWT Component-Peer mechanism is an instance of using the Abstract Factory pattern (as well as the Bridge pattern).


Builder

INTENT: Separate the construction of a complex object from its representation so that the same construction process can create different representations.

Online Resources to Builder

Builder is useful when you have several different kinds of complex objects you need to assemble at run-time, but the rules for how to go about assembling them are similar, even though the end-products are different object types. It separates the process of building the object, from the object itself once it is created. So there may be similar ways of constructing the different objects, but once constructed the objects may exhibit very different behavior.

[follow this link to see the UML diagram]

The Builder pattern involves an object called a Builder and another one called a Director. The Builder object is just an abstract interface for creating parts of some Product object to be constructed. Concrete subclasses of builder know how to put together different kinds of parts for different kinds of products. But they don't know what it is they are building. That's where the director comes in. The Director knows what needs to be built, and it knows the recipe for how to build it. But it doesn't know how to put individual parts together, the Builder objects do that. So the Director gathers the tools and materials and uses the Builder interface to direct the builders to put the various parts together.

JavaBeans are like this to some extent. Any given bean can serve any number of purposes and have different behavior. But many of the same recipes apply for how to construct and use them, thanks to the naming conventions and construction rules in the JavaBeans spec. A GUI Builder environment for JavaBeans doesn't know what you want to build, nor does it know which combination of beans you want to use to construct your application. But it does know how to compose and connect individual beans using events and listeners and adapters and properties. So the GUI Builder environment serves as the "Builder" and the user is the "Director."

Alexander Ran explains how the Java AWT Graphics class uses creators and directors and drawers as an instance of the Builder pattern.


Factory Method

INTENT: Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

Online Resources to Factory Method

A Factory Method is sometimes dubbed a "virtual constructor." It is similar to the clone() method in Java objects. If you have a reference declared to be of type Object, but the thing that it references is really some subclass of object, then even though all you see is an "Object" reference, calling the "clone()" method will create a copy of the appropriate object subclass and return the result. However, this requires that you already have an object to begin with, whereas Factory Method does not.

[follow this link to see the UML diagram]

A factory method is basically some static class method that is declared to return a pointer to some interface or abstract class. It creates an instance of some class or subclass that implements the required interface or is a subclass of the declared class, but returns it as a reference to an interface or abstract class. This way, the caller of the factory method never needs to know the particular concrete class instance that was constructed and returned. It only cares about the published abstract interface.


Prototype

INTENT: Specify the kinds of objects to create using a prototypical instance and create new objects by copying this prototype.

Online Resources to Prototype

Like the clone() method of Object, this pattern requires an object to create an object. The user creating the new object does not need to know the specific class of the object to create. All they need to have is a reference to the prototype object, and how to tell that prototype to clone itself, producing a new object of the same underlying class as the prototypical instance. The newly created instance may then be modified by accessing and manipulating its variables or behavior, while the prototype object remains pristine, and is used solely for reproductive purposes.

[follow this link to see the UML diagram]


Singleton

INTENT: Ensure a class has only one instance and provide a global point of access to it.

Online Resources to Singleton

Sometimes the nature of the problem being solved requires that at most one instance of a particular class is created. This is done by making the class constructor non-public. Then the class has a static method that returns a reference to the lone instance of the class. This static method is responsible for initially creating the singleton instance if it doesn't already exist.

Java introduces some special GOTCHAs when trying to implement a Singleton. If the only reference to a class instance is from the class itself, the JVM thinks it is okay to unload the class (which causes it to be garbage collected). If it is accessed again later, than the JVM will reload it and recreate the singleton object. If it is important that the constructor and finalize methods never execute more than once during the lifetime of the application, then this poses a problem. The JavaSingleton page at the WikiWeb discusses the problem and presents one way to solve it. This same website also has another webpage which identifies and solves another Java Singleton problem.


Structural Design Patterns


Adapter

INTENT: Convert the interface of a class into another interface that clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interface.

Online Resources to Adapter

An adapter is basically a kind of "glue" or "putty" class that lets you put a square peg into a round hole (or an AC plug into a DC outlet). It plugs in one interface into another interface and translates or converts between them as a communications conduit between two objects that don't speak the same language.

[follow this link to see the UML diagram]

JavaBeans GUI Builder tools make use of Adapter classes to bind bean properties together using events. It autogenerates the code for a class that listens to the events for a property of one bean, and notifies the property of the other bean when something happens to it, even though the two beans have no direct knowledge of one another.


Bridge

INTENT: Decouple an abstraction from its implementation so that the two can vary independently.

Online Resources to Bridge

Bridge is another somewhat complicated pattern. The structure is very similar to an Abstract Factory, only instead of being used to create things, the dual class hierarchies are used to perform things, while allowing the interface hierarchy and the implementation hierarchy to vary independently. Alexander Ran explains how the Java AWT Component-Peer mechanism is an instance of using the Bridge pattern (as well as the Abstract Factory pattern)

[follow this link to see the UML diagram]

Using a bridge, I have two different interfaces or abstract classes at the root of two different hierarchies. At the root of the interface hierarchy, I have an interface that represents a logical or functional abstraction (like a Window). At the root of the implementation hierarchy, I have a class that represents the core physical implementation of such an abstraction (like a WindowImpl). Subclasses of the Window class would represent functional extensions, like an IconWindow, or a TransientWindow, or a DialogWindow or a PopupWindow. Subclasses of the WindowImpl class represent implementation-specific variants, like a MacWindow or a UnixWindow.

So we have two separate hierarchies, one for interface and one for implementation. The "bridge" comes from the fact that a class in the interface hierarchy contains a reference to a class in the implementation hierarchy. This line connecting the two hierarchies forms the "bridge" between them. The interface class simply implements its methods by forwarding all its calls to the appropriate methods of the implementation object that it references. Clients know only about the logical functional abstraction they are using, and need not be aware of the particular class that implements it.

For this reason, Bridge is sometimes called "Handle-Body" or "Handle-Body" hierarchy: because the classes in the interface hierarchy merely serves as an opaque "handle" to a class in the implementation hierarchy that delegates all its behavior to be performed by the "body" class referenced by the handle.

Alexander Ran explains how the Java AWT Component-Peer mechanism is an instance of using the Bridge pattern (as well as the Abstract Factory pattern). Abstract Factories are often used to create or construct the classes in a Bridge.


Composite

INTENT: Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

Online Resources to Composite

Composite is fairly straightforward. You have an interface that is common across a hierarchy of objects (they all implement the same core interface). Some of those objects are atomic, and some of those objects may be composed of other objects which also implement the same core interface as their container. So when an operation is carried out on one of these "composite" objects, the composite is responsible for propagating that method-call to its constituents by iterating through the objects it contains and invoking the same method on each one that was invoked of the composite.

[follow this link to see the UML diagram]

Alexander Ran describes how the Java AWT's Container and Component classes, and MenuContainer and MenuComponent classes are examples of a hierarchical Composite relationship.


Decorator

INTENT: Attach flexible additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

Online Resources to Decorator

Decorator provides a way of using composition instead of inheritance in order to extend the behavior of an object at run-time. Let's say I have a MultiLineTextEntryField and I want to add scrollbars. But I'd have to create a subclass for every possible combination of features I'd want to enhance the textfield with.

[follow this link to see the UML diagram]

Instead, I can create an object that implements the same interface, and contains a textfield, but which can also contain a set of zero or more "decorations" that add some behavior to the textfield. The basic operation can be "forwarded" to the textfield object. But any additional or enhanced operations might be passed on to one or more decoration objects instead or, or in addition to, the text-field object.


Facade

INTENT: Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.

Online Resources to Facade

A Facade is used to create higher-level subsystems from lower-level building blocks while hiding the complex interface of the interaction between the building blocks. A bunch of objects might be put together in a certain way to accomplish a certain task. And while it would be possible for clients to remember the right group of objects and the right way to make their interfaces work together, a "Facade" object is placed between the group and its client.

[follow this link to see the UML diagram]

So the Facade worries about the details of which objects are in the set and how to configure them to interact properly, even though the client could have done this using the public interfaces. And the Facade presents a much simpler interface to the client, makes it look as if the functionality is being provided by a single black box, instead of from several small interacting elements plugged together.


Flyweight

INTENT: Use sharing to support large numbers of fine-grained objects efficiently.

Online Resources to Flyweight

Suppose I have a matrix or spreadsheet that is basically made up of only a dozen or so basic elements, but repeated and combined thousands of times in various ways throughout each of its cells? Rather than have thousands of copies of only a dozen or so smaller elements, it might make more sense to have only a dozen instances created, and have all the other cells contain a reference to the smaller object instead of a separate copy.

[follow this link to see the UML diagram]

This makes good sense as long as the size of the object is larger than the size of a reference to an object. The smaller elements, that are shared by the thousands of cells, are called "Flyweight" objects.


Proxy

INTENT: Provide a surrogate or placeholder for another object to control access to it.

Online Resources to Proxy

We've already seen an example of a Proxy in the way Java does RMI. The "Stub" object generated by the RMI compiler (rmic) is just a local proxy or surrogate for the real object on the remote machine. In reality, it doesn't implement the object's behavior or state directly. It just performs remote procedure calls to send the request to the real object, and then sends the result back to the client on the local machine.

[follow this link to see the UML diagram]


Behavioral Design Patterns


Chain of Responsibility

INTENT: Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.

Online Resources to Chain of Responsibility

In some ways, the old AWT broadcast event model was a kind of "Chain of Responsibility." As of Java 1.1 and later, the AWT uses a Publish-Subscribe model (a variant of the Observer pattern). Parties interested in notification of a particular event must explicitly register their interest in the event with the generator of that event. The former subscribes to the event notification service and the latter publishes event notifications to its subscribers.

But in Java 1.0, the AWT used a "Broadcast" model instead of a Publisher-Subscriber model. When an event occurred, the object generating the event was first consulted to see if it wanted to handle the event. If it did, then that was the end of it. If not, then each container of that object was consulted in turn to see if it would like to handle it. If none of them did, then the containers of all those objects were consulted, until somebody somewhere up the tree of that object's containment hierarchy either explicitly handled the event, or gave an explicit failure.

[follow this link to see the UML diagram]

The Chain of Responsibility (COR) pattern uses a chain of objects that is responsible for handling one or more operations with the first object on the chain getting first crack at handling the request. When a request is made, the first object decided whether to handle it. If it does, great; all finished. Otherwise it can pass the buck to the next object in the chain and let it have a chance to fulfill the request.

Note that, according to the GoF book, the COR pattern involves traversing up a list or a tree from more specific handlers to more general handlers. Traversing down a tree is not the COR pattern; it is the Composite pattern!

Alexander Ran describes how the Java AWT's Container and Component classes participate in a Chain of Responsibility relationship.


Command

INTENT: Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undo operations.

Online Resources to Command

We've kind of seen an example of this pattern already in third programming assignment for this class. We had to create a minimal HTTP server that served up files to requesting clients via a socket connection. The Java Distributed Computing book by Jim Farley created an abstract command object to represent client requests. Then concrete subclasses were created for each request command, and one need only invoke the Do() (or Execute()) method of a command in order to carry out the request.

[follow this link to see the UML diagram]


Interpreter

INTENT: Given a language, define a representation for its grammar, along with an interpreter that uses the representation to interpret sentences in the language.

Online Resources to Interpreter

An Interpreter can be used to evaluate the results of an expression given as a sequence of operations, operators, and operands. An expression consists of one or more "terms." A term can be be a value, or it might be an operation which requires a single operator and one or more operands. Each operand might be another term: either a single value or yet another operation. We can represent each operation and operand as an object with an "evaluate()" or "interpret()" method that returns the result of the operation, or the value of an operand.

[follow this link to see the UML diagram]

So we have an abstract Expression class or interface with an "interpret()" method, and then we have TerminalExpressions, which are single values, and NonTerminalExpressions, which are Composite objects containing multiple Expressions that need to be computed together somehow. There might also be a Context object that stores information about the circumstances in which the expression is being evaluated (this might be used to communicate things like operator precedence, or global information about symbols or variables used in the expression).

This lets us build up an expression as a tree of Expressions, and then interpret the result be invoking the "interpret()" method of the root of the tree, which takes care of sending the interpret() message to all the subexpressions and interpreting their results in the right way to return the overall answer to the caller.


Iterator

INTENT: Provide a way to access the elements of an aggregate object sequentially with out exposing its underlying implementation.

Online Resources to Iterator

We've already seen an example of this as well. The class java.util.Enumeration is an example of the Iterator pattern. It represents and abstract means of iterating over a collection of elements in some sequential order without the client having to know the representation of the collection being iterated over. It can be used to provide a uniform interface for traversing collections of all kinds.

[follow this link to see the UML diagram]


Mediator

INTENT: Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and lets you vary their interaction independently.

Online Resources to Mediator

Remember the Chat Server example used in lecture to illustrate the Observer pattern? The same example could have been used to illustrate the Mediator pattern as well. In the example, each chat-client was an observable object that could be observed by every other chat-client. So each chat-client had be both an Observer and an Observable.

This was unfortunate because it means that each of the N chat clients has to register with each of the other N-1 chat clients. That's a lot of registration overhead, and it only gets harder to maintain every time a new chat-client joins the conversation, or an existing one leaves. It was so much overhead in fact that Dr. Coyle used a separate registration manager object to handle all the registering and unregistering of observers and observables.

A nice solution to this N*(N-1) registration problem would have been to use a Mediator object instead of a manager object. A Mediator could have been used to represent the current content of the conversation. It would serve as the ConversationalDialogue that each chat-client needed to see. Then instead of each chat-client needing to be both observers registering with all the other observable chat-clients, each chat-client could have simply registered to observer with only one object: the observable mediator serving as the ConversationalDialogue. This requires only N registrations instead of N*(N-1), and only 1 (un)registration (instead of N -1) when a chat client joins/exits the conversation.

[follow this link to see the UML diagram]

Aside from decreased registration overhead, the mediator helps eliminate the need for the mediated objects to know about the existence of one another, they only need to know about the mediator, which decouples them from the other mediated objects and reduces their inter-dependencies. The mediator serves as a kind of "Rosetta Stone", providing only one translation and communication from the mediator into each mediated language (and vice versa). Instead of requiring direct translations from each mediated language to every other mediated language, it lets the communicate back and forth via the mediator knowing only their own native tongue, and the mediators universal tongue.

Alexander Ran explains how the Java AWT FocusManager class acts as a mediator between Containers and Components.


Memento

INTENT: Without violating encapsulation, capture and internalize an object's internal state so that objects can be restored to this state later.

Online Resources to Memento

The basic idea here is to create some kind of "snapshot" of an object, so that the object may later be restored from the snapshot. So an originating object creates a memento of its current state which is then stored in some caretaker for such mementos. At a later time, when the originator needs to recall or reset its previous state, it asks the caretaker to return the previously stored memento, and the object can restore its state from that. The tricky part of this is doing it in such a way so that the caretaker object requires no knowledge of any of the implementation details about the mementos it holds.

[follow this link to see the UML diagram]

Java's object Serializable and Externalizable APIs can capture and restore the entire state and data of an object. In fact GUI Builders using the JavaBeans spec rely on this extensively so that beans and beaninfo can be captured in jar files.

But it's important to understand that a Memento need not always capture the entire object. It only needs to capture enough information so that the originator can recall its own state. It may be possible that storing only a few pieces of information in a memento is sufficient for the originator to determine how to reset the values of a few dozen or more fields. For example, if a certain value in a memento is only possible when a half dozen fields are in a particular configuration with known values, then that one value allows the originator to determine the previous values of the other half dozen values.


Observer

INTENT: Define a one-to-many dependency so that when one object changes state, all its dependents are notified and updated automatically.

Online Resources to Observer

As was shown during lecture, Java provides direct support for implementing the Observer pattern via the java.util.Observer interface and the java.util.Observable class in the Java API. It is a form of one-to-many relationships between a single publisher of an event, and many subscribers to the event that wish to receive notification. The observing objects need only to know how to register for an event, and the observed object needs to know how to notify them.

[follow this link to see the UML diagram]

The observers don't have to wait around or continuously query to find out whether the event the care about has occurred, the simply register and await notification. When the observers register with the observable, the observed object essentially says to them "don't call me back; I'll call you back!"

Alexander Ran explains how the Java AWT ImageObserver class uses subjects and observers to implement a variant of the Observer pattern.


State

INTENT: Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.

Online Resources to State

Many of the above resources use the term "State" in the context of Finite State Machines (or FSMs) for their examples. It is very important to realize that the "State" pattern isn't referring so much to states of a finite-state machine as it is to the "state" of a particular object, which is the set of values of all its member variables. The purpose of the state pattern is not to mimic the behavior of state-machines, it is to allow an object to appear to alter its behavior-type at run-time. If you have an objects that actually has FSM-like states, then the State pattern is not necessarily appropriate to use unless the object's methods need to behave very differently after a state transition!

[follow this link to see the UML diagram]

One classic example using State is of a caterpillar, that turns into a pupa, and then later metamorphoses into a butterfly. It is the same animal with the same identity during its lifespan, but at various phases of its life, it exhibits different behaviors (like flying versus crawling), or else the same behaviors in different ways (like eating, or travelling).

The standard way to do this is with a single "handle" class which holds a reference to a single "body" class, but can change the handle at run-time to refer to any class that implements the same interface as the handle-class. So the handle class always forwards its method invocations to the body-class that it reference, but any any given time, the handle may be referencing a different implementation of "body" class than it did previously.


Strategy

INTENT: Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from the clients that use it.

Online Resources to Strategy

The Strategy pattern defines an abstract policy for performing an algorithm, At the same time it provides multiple mechanisms that can comply with that policy, thus letting mechanism vary independently from the policy required. For example, suppose I have a policy representing the properties I require to access a linear collection of elements. I have an addElement() method, a removeElement() method, a currentElement() method, and a nextElement() method.

At the same time, different clients might want to traverse the list differently, and add and remove items differently. Some might want to traverse the list from front to back (top to bottom) or from back to front (bottom to top). Independently of traversal strategy, some might want element to be inserted and removed using a Last-In-First-Out strategy (LIFO) like a stack, or a First-In-First-Out strategy (FIFO) like a queue.

Each instance of these different strategies could be coded up into a strategy object. I'd have a TopDownTraversalStrategy class and a BottomTraversalStrategy class that both implemented the same SequentialTraversal interface; as well as a LIFOModificationStrategy and a FIFOModificationStrategy that both implemented the same ListModifierStrategy interface. A new List object could use a particular combination of these two strategies by default, but could allow a client-specified strategies to be supplied at list creation time (to be used instead of the defaults).

[follow this link to see the UML diagram]

This is similar to the way AWT LayoutManagers work. There is an abstract LayoutManager class/interface that specifies the policy with which each layout management strategy must comply; and then there are multiple concrete layout manager classes for things like GridLayout, FlowLayout, etc. which provide different behavioral mechanisms for implementing a layout strategy. Alexander Ran also explains how the Java AWT Layout Managers are an instance of the Strategy pattern.


Template Method

INTENT: Define the skeleton of an algorithm in an operation, deferring some steps to its subclasses. Template method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.

Online Resources to Template Method

Template methods are fairly common. Consider an abstract InputStreamImpl class for providing the common implementations needed by most types of input streams. It might have a method for doing a getLine(), getChar(), getToken(), skipChars(), etc. What it can't necessarily know is the specific details of how to read a single byte from all possible streams. This will differ between files and sockets and pipes and strings and text-entry-widgets for which input stream implementations can be provided.

So the InputStreamImpl class might declare an abstract method named "readByte()" that all concrete subclasses must implement. Then the InputStreamImpl can code up the implementation of the methods like getLine() and getChars() and skipChars() using the abstract readChar() method. The readChar() method is considered a "primitive operation" and the methods that use the abstract primitive operations to implement concrete behaviors are called "Template Methods" because they are a template for how to perform the behavior that defers primitive details to be filled-in later by subclasses.

[follow this link to see the UML diagram]

An example that hits a little closer to home might be extending a Java Applet or a Thread. When you extend the Applet class in Java there are several "primitive methods" that you are supposed to implement: init(), paint(), start(), and stop(). Similarly when extending the Thread class you need to implement the run() method. But the extending subclass isn't the primary invoker of these methods. In most cases, it is the superclass (or some other class) that knows the appropriate time to invoke them, and which performs some kind of set-up before and/or after the call.

Incidentally, template methods are sometimes used in combination with abstract private methods. An abstract private method make not make any sense, because if no one can invoke it except the superclass, but the supeclass doesn't implement it, then what good is it? Well, making the method abstract lets the subclasses fill in the missing behavior but leaves control over when it gets called upto the superclass (because a subclass can implement a private abstract method, even though it can't invoke it).


Visitor

INTENT: Represent an operation to be performed on elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.

Online Resources to Visitor

Visitor is perhaps the most complex of the GoF design patterns. Suppose you have some complicated hierarchical structure of objects. Each object in the structure may be an instance of a different object class. Yet there may be a host of operations that you wish to perform on each object in the structure. Unfortunately, each different type of object may need to respond to the operation request in a different way. The operation doesn't know the details of how the different objects need to behave differently. At the same time, the objects don't necessarily know the details of the particular operation that is performed upon them.

When we learned about polymorphism, we learned that different objects supporting the same interface can implement the same method-interface in their own different way. The method-name and parameters stay the same, but the implementation that is invoked can vary at run-time for each different object.

If you think of the object whose method is invoked as being the implicit first parameter to the method, then the result is that the underlying class of the first argument is used to decide which method implementation to dispatch. Since this dispatching is performed dynamically at run-time, this is often referred to as dynamic dispatch. Most object-oriented programming languages support dynamic-dispatch based on the type of this implicit first-argument. This is called single-argument dispatch (or just single-dispatch).

The problem that Visitor solves is one in which the particular implementation to use may vary depending on the class of two arguments instead of just one: the class of operation to be performed, and the class of the object to operate on. This is called double-dispatch. A few O-O programming languages actually provide direct support for double-dispatch (CLOS is one of them). Methods that are dispatched based upon multiple arguments (rather than just one) are often called multi-methods and they require multiple-dispatch.

But Java and C++ and Smalltalk and many other popular O-O programming languages don't support double-dispatch. We have to find our own way to program it. This is what the Visitor pattern does. It "fakes up" double dispatch by using a sort of two-way polymorphic handshake: First, a particular instance of an operation (a "visitor") visits each object in the structure and asks it to accept this visitor by invoking the object's acceptVisitor() method. Then, the object's acceptVisitor() method invokes the "Visit" method of the visitor that is tailor made for operating on that type of object.

[follow this link to see the UML diagram]

Some sample code follows:


   public interface Visitee {
      public void acceptVisitor(Visitor v);
   }

   public abstract class Visitor {
      public void VisitObjects(Enumeration visitedItems) {
         while (visitedItems.hasMoreElements()) {
            // The visitor object asks the visitee to accept this visitor
            Visitee obj = (Visitee) visitedItems.nextElement();
            obj.acceptVisitor(this);
         }
      }

      public abstract void visitTypeA(Visitee obj);
      public abstract void visitTypeB(Visitee obj);
      public abstract void visitTypeC(Visitee obj);
        // ... and so on, for each type of object to visit
   }

   // Now some concrete visitor classes for various operations to
   // perform on the structure, e.g., "Print", "Display", "Compute",
   // "Save", "Clear" ...

   public class ConcreteVisitorA extends Visitor {
      public void VisitTypeA(Visitee obj) {
         //  ... do what needs to be done for a TypeA object
         //  for this type of visit-operation
         obj.doSomething();
      }
      public void VisitTypeB(Visitee obj) {
         //  ... do what needs to be done for a TypeA object
         //  for this type of visit-operation
         obj.doSomethingElse();
      }
        // ... and so on, for each type of object to visit
   }

   public class ConcreteVisitorB extends Visitor {
      // ... same stuff as above, but for a different operation,
      // e.g., "Print", "Display", "Compute", "Save"
   }


   // Now for the types of objects in the structure that we need to visit

   public class TypeA implements Visitee {
      public void acceptVisitor(Visitor v) {
          v.VisitTypeA(this);
      }
      // ...
   }

   public class TypeB implements Visitee {
      public void acceptVisitor(Visitor v) {
          v.VisitTypeB(this);
      }
      // ...
   }

Here, in detail, are the two parts of that two-way polymorphic handshake:
  1.       public void VisitObjects(Enumeration visitedItems) {
             while (visitedItems.hasMoreElements()) {
                // The visitor object asks the visitee to accept this visitor
                Visitee obj = (Visitee) visitedItems.nextElement();
                obj.acceptVisitor(this);
             }
          }
    

    This is the first half of the polymorphic handshake. Single-dispatch based on the class of the operand object is performed by invoking its acceptVisitor() method. acceptVisitor takes a parameter of type "Visitor" which is the abstract interface for all operation "classes" that may be performed over the object structure. This uses polymorphism to select the proper class of operand to operate upon.

  2.       public void acceptVisitor(Visitor v) {
              // invoke the operation of the visitor named after this type
              v.VisitTypeA(this);
          }
    

    The second-half of the polymorphic handshake is that single-dispatch based on the class of the Visitor operation is performed by the acceptVisitor method invoking the visitTypeX method of the Visitor object, and passing itself as an argument to the visitor (where TypeX is the name of the class of object being visited).

    Since the TypeX implementation of the acceptVisitor method knows its own class, it knows which method of the Visitor to invoke (because it will have visitTypeA(), visitTypeB(), etc., for each class of object that can be visited). So it completes the handshake by selecting the correct method name to invoke, and then using polymorphism to select the correct implementation of that method.

The cumbersome part is that each type of visitor object needs to have a separate visitTypeX method for each kind of object it might visit (operate upon). This makes adding new operations easy, but somewhat tedious. Unfortunately, it seems to be the best workaround when double-dispatch is not supported by the language.

So a particular class of visitor visits each object in the structure and calls its acceptVisitor method, passing itself as a parameter to the visited object. This is the Visitor object extending its hand saying "please accept me polymorphically." Then the visited object responds by invoking the proper visitTypeA method of the visitor, and passing itself as a parameter back to the visitor. This is the visited object extending its hand back to the visitor, shaking its hand, and saying "Yes, I polymorphically accept you; Now you may polymorphically operate upon me."

And that's why I refer to Visitor pattern as "faking double dispatch" via a two-way polymorphic handshake between different classes of operations that may each be performed on different classes of object in a structure. (Whew!)


Part III:
Java and Distributed Computing Patterns

Java Patterns on the WikiWeb
Component Design Patterns on the WikiWeb
Doug Schmidt's ACE - Concurrent/Distributed Design Patterns
Kyle Brown's Objects to RDBMS, and 3 Tier Architecture Patterns
Doug Lea's Concurrent Java Patterns
Other Design Patterns for Java and Distributed Computing
Synopses of Mark Grand's Design Patterns in Java


Now that we've provided a basic tutorial on what patterns are, and what the most widely known set of O-O design patterns are (the GoF design patterns), we are ready to find out about other design patterns to use for Java Distributed Computing. I'm not going to describe these patterns in any detail like I did with the GoF patterns. I just wanted to provide enough background so that you would be able to dive into them yourself (since many of them assume prior knowledge of the GoF patterns).

So I'm basically just going to provide a set of hyperlinks to different patterns and pattern collections, and say very few words about each individual pattern.


Java Patterns on the WikiWeb

There are an incredibly large number of Java and distributed computing patterns on the Wiki Web. These need a bit of explaining. The Wiki Web is a website created by Ward Cunningham for collaborative authorship. This means that anyone can create a page on the Wiki Web for almost any purpose (within reason, as long as it's deemed relevant). So there are a great many pages on the Wiki Web devoted to patterns. All varieties of pattern formats are used, but the most common ones are canonical form, and a few different prose forms that don't use section titles.

Furthermore, since pages on the Wiki are collaborative, a great deal of discussion takes place on many of these pages. So they should rarely ever be considered "finished works." Often an idea may be hotly contested as to whether or not it is at all desirable. So you can't necessarily assume that any pattern written-up on the Wiki Web is any good. But you can still learn a lot from reading the ensuing discussion.

Here is a run-down of most of the Java-related patterns on the Wiki web. These are taken primarily from various summary pages on Java Patterns, Java Idioms, Exception Patterns, and Distribution Idioms.

  Architectural Idioms

  Type-Safety

  Memory Management &
  Reference/Value Semantics

  Object Creation, Initialization
  and Construction

  Using Enumerations & Collections

  General Workarounds & Miscellanea

  Using Exceptions

  Using Exceptions (continued)


Component Design Patterns on the WikiWeb

These are also on the Wiki web but deserve separation mention because not only is there a considerable number of them, but they are part of a large "in progress" effort to document a cohesive and coherent Component Design Pattern Language. That means they are more than just a set of related patterns. It means the authors (Phil Eskelin, Kyle Brown, and Nat Pryce) are trying to show how all the patterns are used together to create complete Component Technology Systems and Architectures. So not only does each pattern try to solve an individual problem, but each one plays a part in achieving this overall goal; and the others try to show how the patterns fit together in order to do just that.

Once again remember that this is a work-in-progress, so there is a great deal of discussion on many of these pages, and many of the patterns are incomplete, or or in the process of being converted from one pattern form to another. Here is the current status of the Component Design Pattern Language.

Component Design Pattern Language on the Wiki Web


Doug Schmidt's ACE - Concurrent/Distributed Design Patterns

Doug Schmidt is a well known export in the Design Patterns, CORBA, and C++ Communities. He has done extensive research, programming, and design of distributed object systems using cutting edge technologies, much of which often sets the pace for what future versions of CORBA are expected embrace.

Doug and his colleagues have documented an impressive collection of Design Patterns for Concurrent, Parallel, and Distributed Systems developed as part of the ACE Project. Most of these patterns use C++ examples, but they are very powerful and important techniques for concurrent and distributed object systems that apply to Java just as much as to C++. We've already learned about one of these in class, "Thread Pool." Here are links to each of these papers (most of which are in postscript format) along with a brief abstract of each pattern.

ACE Event Patterns

ACE Concurrency Patterns

ACE Initialization Patterns

ACE Miscellaneous Patterns


Kyle Brown's Objects to RDBMS, and 3 Tier Architecture Patterns

In addition to what you've already seen above regarding tutorials and Java idioms and Component Design Patterns, Kyle also has some patterns papers at his own website.

The first, and probably most well-known patterns paper of Kyle's (actually Kyle is only one of multiple authors) is a pattern language entitled Crossing Chasms. The pattern language as a whole addresses the issues faced by teams trying to build large client-server systems using Object Technology and Relational data stores. The example we saw in class of storing objects in a relational database using the JDBC and object serialization is only the tip of the iceberg. All it does is use the underlying database as if it were a hashtable. It doesn't provide the ability to store relationships between any of the objects or to query those relationships and retrieve the resulting objects.

Trying to sensibly map object systems to relational database systems to take advantage of all the benefits of both object-orientation and relational databases is an incredibly difficult task. Kyle and friends tackled this problem early on and produced this pattern language to document their solutions and decisions. Several commercial vendors now have industrial strength products which use these patterns to help clients may their object systems into an RDBMS.

The second paper documents Patterns of Three-Tier Client-Server Architectures. Some of these patterns are also part of the Crossing Chasms pattern language.


Doug Lea's Concurrent Java Patterns

Doug Lea is another long-standing guru in the areas of design patterns, concurrency, and Java. He has written a book entitled Concurrent Programming in Java: Design Principles and Patterns. Fortunately he has made much of the material for his book and patterns available at his website as part of an online supplement. Doug didn't use any particular pattern format in the 1st edition so it's not always easy to tell what is supposed to be a pattern and what isn't. The author claims some of these will be fixed in the 2nd edition (which is not yet available).

Professor Sandeep Singhal, of IBM Research, has prepared a set of slides discussing some of Doug Lea's Design Patterns of Concurrent Object Systems as part of of a course he co-teaches at the University of North Carolina.


Other Design Patterns for Java and Distributed Computing

Sandeep Singhal has also created a set of slides discussing Design Patterns for Distributed Object Systems. These patterns are commonly used in distributed object design.

Dirk Riehle's Patterns Publications are another set of insightful patterns about object-oriented design, many of which use Java examples.

Antonio Rita Silva's DASCo Patterns project contains numerous papers documenting design patterns about object-oriented frameworks for distributed and concurrent systems.

The ARCUS Design Patterns projects also contains a number of papers documenting patterns for GUI design, mapping objects to relational databases (e.g., Relational database access layers)

Model-View-Presenter or MVP is a next generation programming model for the C++ and Java programming languages. MVP is based on a generalization of the classic MVC programming model of Smalltalk and provides a powerful yet easy to understand design methodology for a broad range of application and component development tasks. The framework-based implementation of these concepts adds great value to developer programs that employ MVP. MVP also is adaptable across multiple client/server and multi-tier application architectures. MVP will enable IBM to deliver a unified conceptual programming model across all its major object-oriented language environments.

Bill Venners' Design Techniques Articles are a good source of information of Java design using patterns (even though not all of the articles talk about patterns).


Synopses of Mark Grand's Design Patterns in Java

Mark Grand has authored a 3 volume series of design patterns. They aren't all available online, but he does have a synopsis of the contents of each volume.

Design Patterns in Java - Volume 1

The 41 patterns in Volume 1 are organized into categories as shown below.

  Fundamental Design

  Creational

  Design Partitioning

  Structural

  Behavioral

  Concurrency Design

Design Patterns in Java - Volume 2

Volume 2 contains patterns that apply to phases of the software development cycle other than design. The 50 patterns in this volume are organized into the following categories:

  GRASP Patterns

  GUI Design

  Code Organization

  Code Optimization

  Code Robustness

  Testing

Design Patterns in Java - Volume 3

Volume 3 is currently in-progress. The focus of this volume is intended to be design patterns for distributed enterprise design. It will encompass patterns for the categories of:


[Back to the Table of Contents]