Boulder Patterns Group Minutes

After several complaints that these pages form a WalledGarden, the Boulder Patterns Group pages have moved to http://BoulderPatternsGroup.org/ . Please go there for current information.



This is a page for details of the meetings of the BoulderPatternsGroup. Further information on topics discussed at the meetings is available in BoulderPatternsTopics?. For the minutes of meetings from previous sessions see BoulderPatternsGroupMinutesOld?.


7th October 2002

We discussed Decorator, Composite and Adaptor. I don't have any images of the UML for these patterns handy - if anyone knows where to find them, then please email me (RobJudd) or put them into this page yourself.

Decorator

Add responsibilities to an object dynamically. This may be done with inheritance, but a more flexible approach is to enclose the object in another object that adds new behaviour.

Decorator subclasses are free to add operations for specific functionality. If a client knows that it has a specific Decorator subclass, then it may use the additional methods, but generally clients can't tell the difference between a decorated pattern and an undecorated one.

Use Decorator Examples

One issue to be aware of is that the component from which the decorator inherits must be lightweight; it should focus on defining an interface rather than storing data. An alternative for heavyweight classes is the Strategy pattern.

Composite

Allow clients to treat single objects and hierarchies of objects the same way.

Two types of class descend from a common parent: composite nodes which may contain children, and leaf nodes (which have no children). Generally the client only sees the type of the common ancestor and so treats all objects the same.

One issue to be aware of is where in the class hierarchy are the child management methods defined. If they are in the common parent, then they can add extra memory and may not make sense for leaf nodes. If they are in the composite, then the client must distinguish between composite and leaf nodes in order to manage children. Which you choose depends on the problem you are trying to solve.

Examples

In the first example the child management methods are in Container, not its parent, Component. In DOM these methods are in the parent class. JUnit A Cook's Tour provides a full description of patterns applied to the design of JUnit (see section 3.5 for a peek at Composite): http://junit.sourceforge.net/doc/cookstour/cookstour.htm

Composite vs Decorator

Decorator may be thought of as a degenerate example composite pattern - where decorator subclasses have exactly one child. However, this ignores the intent of the two patterns. Decorator allows dynamic and transparent addition of responsibilities, while Composite allows clients to treat single objects and hierarchies of objects the same way.

Adaptor

Convert an interface you have into one that your client expects.

GoF talk about two types of Adaptor: a class Adaptor and an object Adaptor. A class Adaptor inherits from both the interface that the client expects, and from the Adaptee (the class that is being adapted). An object Adaptor relies on object composition. The Adaptor inherits from the interface that is being adapted, and keeps a reference to the Adaptee. Class Adaptors require fewer objects, but are less dynamic than Object Adaptors.

Object Adaptor

Class Adaptor

There was some discussion about the difference between Adaptor and Facade. In general Adaptor has a one-to-one relation between Adaptor and Adaptee, while Facade has a one-to-many relationship between the Facade class and the classes in the subsystem that it is simplifying. However it is quite possible that you might use an adaptor to adapt an interface using several classes. As usual, the difference lies in the intent: Adaptor is for matching an interface, while Facade is for simplifying a system.

Examples

No-one had any real-life examples.


For Additional Information See Related Pages: AdapterPattern CompositePattern DecoratorPattern
A note on the spelling of Adaptor.

GoF spells this as Adapter so I looked it up in the Oxford English Dictionary. They have both spellings with a note that adapter is more commonly used to describe a person (one who adapts), while adaptor describes a device.

21st October 2002

We discussed Abstract Factory, Factory Method, and Prototype.

Factory Method

Define an interface for creating an object, but let subclasses decide which class to instantiate.

This is similar to Abstract Factory except that there is only one method that is called to create the class, and only one abstract type is returned. Notice, however, that the intent of the pattern is flexibility: the client may only see the interface of the product, and the object creation is intended to be handled by subclasses. For example, java.text.NumberFormat?.getInstance() does not fit this pattern since it is a final static method, not designed to be overridden.

The interface for creating an object is usually a small part of a larger interface; one rarely sees a class dedicated to a single factory method.

This is best illustrated with an example. In the Java Collections framework, the Collection interface, defines the following method:
  public Iterator iterator() ;
This method is a factory method that creates and returns an Iterator suitable for stepping through the collection (see IteratorPattern). Concrete implementations of Collection include LinkedList, Vector, and TreeSet?. Each of these may implement the method as it pleases to return an Iterator most suited to it. The interface of Iterator is very small, just two methods that are required, and no class that uses one needs to know any more than this interface.

One of the drawbacks of this pattern is when the clients that use the products need to know more about the product than its general interface.

Abstract Factory

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

A client obtains new instances of a family of classes by calling the appropriate create method on a factory class. The client may not know the concrete factory class being used; all the client needs to know about is the abstract factory interface. The concrete class that the client uses may be specified at runtime (and changed then, also) or at compile time.

One thing to note is that this pattern allows the programmer to separate the creation of an object from its use, producing parallel hierarchies of products and creators. Unfortunately this is also one of the problems with this pattern. If you want to add another class to your product hierarchy, then you must update each class in the factory hierarchy.

Times to use this pattern include:

The classic uses of this are the low-level implementations of windowing tool kits, or look-and-feels.

RMISocketFactory is an abstract factory class that specifies two create methods: createSocket and createServerSocket. In the class library there are classes that extend this factory for specific types of socket.

Concrete subclasses of an abstract factory class are often implemented as singletons (see SingletonPattern). The create methods of an abstract factory class are typically factory methods (see FactoryMethodPattern).

Prototype

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

Prototype should be used when a system should be independent of how its products are created, composed, and represented; and

Many methods that look like they are factory methods are, in fact, examples of Prototype.

java.text.NumberFormat?.getInstance() is an example of the third option. It returns a DecimalFormat? class configured with the appropriate locale.

java.security.MessageDigest?.getInstance(String algorithm) demonstrates the first option. You give it the name of the algorithm you want and it will look up the name of a class that implements that algorithm. The class will then be instantiated using reflection.

Often the prototypes must be initialized after they are returned. An example of this is javax.crypto.Cipher.getInstance(String algorithm). Before this class may be used its init() method must be called.


For Additional Information See Related Pages: AbstractFactoryPattern, FactoryMethodPattern, and PrototypePattern.

4th November 2002

We discussed Singleton, Template Method, Strategy and Builder.

Singleton

Ensure a class has just one instance; provide a global point of access to it.

Some classes only need to be instantiated once; others will break if they are instantiated more than once. Examples: This may be done by having a private constructor in the class and a static access method to an instance of the class. Example code:

	public class MySingleton? {

private static MySingleton? instance = new MySingleton?() ;

private MySingleton?() { // initialise the object }

public static getInstance() { return instance ; }

}

or

	public class MySingleton? {

private static MySingleton? instance ;

private MySingleton?() { // initialise the object }

public static synchronized getInstance() {

if (instance == null) instance = new MySingleton?() ; return instance ;

}

}

When you are multi-threaded the only safe ways to write a Singleton class are to create the instance when the class is loaded using a static initializer, or synchronize the method that returns the instance.

See SingletonPattern.

Below are several links to articles on double-checked locking in Java and why it doesn't work: --Jerry Brown

Strategy

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

client code

  Context myContext
  Strategy myStrategy = Factory.getStrategy(info_from_config)
  myContext.doStuff(myStrategy)

context code

  public method doStuff(Strategy strategy) {
	// create what info needed by strategy
	strategy.doStrategicStuff(info)
  }

What are the other methods to solve this problem?

switch case
have to change the context for each new variation. if we have 2 variations then we can have m*n methods. also low cohesion.

subclassing
combinatorial explosion if we have more than one thing varying.

What happens when we want to add variations of an existing behaviours? Just add a new strategy subclass and add stuff to factory.

What happens when we want to add a new variation? Add a new strategy and add to factory

Problems

Clients must be aware of different strategies as it is the client which chooses strategies. Communication overhead between strategy and context.

Implementation

How to pass data?
in parameters
low coupling, but context might pass data which strategy doesn't need
using context
context pass itself or strategy keep a ref to context - high coupling

Strategy and bridge

similar, but in bridge there are multiple degrees of freedom. ie the context(abstraction) and strategy(implementation) can both vary.

Strategy and state

similar, but the client chooses which strategy to use while usually the concrete state subclasses choose which state to go next.

Navdeep

Builder Pattern

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

Examples from Gof:

1 - RTFReader - TextConverter example

The director role is filled by RTFReader, which is responsible for parsing the RTF file and constructing the product with the desired format (ASCIIText, TeXText, TextWidget). The director uses the builder interface to build the product. A key aspect of this pattern is that the director does not know what concrete builder it is using or what product is being assembled. The director only knows the algorithm for building the product.

The builder in this example is the abstract class TextConverter. All concrete builders implement this interface. The builder hierarchy (builder and its concrete builder subclasses) is responsible for assembling the product. A second key aspect of this pattern is that it separates the algorithm for constructing the product (director) from the actual product assembly (builder hierarchy). The builder interface defines the methods to add parts to the product.

The concrete builders (ASCIIConverter, TeXConverter, TextWidgetConverter) construct the product using the builder interface (TextConverter). These classes are also responsible for storing a reference to the product they are creating. These classes must provide a method for the client to get the product after it is completely assembled. A third key aspect of the builder pattern is that the product is stored in the concrete builder and an assessor method is provided for the client to retrieve the finished product. This is necessary because this pattern is applicable when the potential products are very different from each other. There is no abstract product interface like in the Abstract Factory Pattern.

There is also a client that creates the desired concrete builder, creates the director, and gets the final product from the concrete builder. A fourth key aspect of the Builder Pattern is that the client maintains a reference (temporary or permanent) to the concrete builder so that it can retrieve the product.

2 - Maze Example: This example is interesting because one concrete builder builds a maze while the other merely counts rooms and doors. The two products are very different, but the construction process is the same.

Applicability

Consequences

Implementation

Question from ?A Learning Guide to Design Patterns? by Joshua Kerievsky, Industrial Logic (http://www.industriallogic.com/papers/learning.html)

Like the Abstract Factory pattern, the Builder pattern requires that you define an interface, which will be used by clients to create complex objects in pieces. In the MazeBuilder? example, there are BuildMaze?(), BuildRoom?() and BuildDoor?() methods, along with a GetMaze?() method. How does the Builder pattern allow one to add new methods to the Builder's interface, without having to change each and every sub-class of the Builder?

The new method could be added as a do nothing method in the Builder interface, then implemented in only the concrete builders where it has meaning. If a new concrete builder is being added with this additional functionality, it will not be necessary to add the method to each and every existing builder if the method is not applicable to their products.

For more information see BuilderPattern.

--- SarahSmith


Template Method

While not necessarily part of a package written in an object-oriented language, a nice example of the use of the Template Method is demonstrated by the rendering loop defined in SGI's scene-graph package, OpenGL Performer. The rendering loop is typically locked to an external time-sync generator with numerous method calls guaranteed to occur in a given interval. An abbreviated list of these is:

	App	 <-----

PreCull? <----- Cull PostCull? <-----

PreDraw? <----- Draw PostDraw? <-----

(I have flagged the functions that are typically provided by user-defined methods.)

OpenGL Performer is written in C, not C++, so does not use inheritance. Rather, one must provide function callbacks to routines such as setPreDraw( myFunction ). An example function might render a background image onto which all other drawing is composited.

The Template Method is useful in cases just such as the above when a series of operations must be performed; some of which must remain fixed, some which may be changed and some which must be defined. Inheritance facilitates this pattern's use.

(See diagram in the text.)

Here the templateMethod in the AbstractClass calls a sequence of concrete and abstract methods defined either in the AbstractClass or in its child ConcreteClass?.

NOTES:
  1. Access control in C++ or Java can be used to enforce certain behavior. For example, concrete methods in the AbstractClass that must not be overridden can be specified as not-virtual in C++ or final in Java. Abstract methods that must be overridden can be specified as pure-virtual in C++ or abstract in Java. Finally, all methods called by the templateMethod may be declared protected in order to restrict access to them.

  2. As a rule of thumb, try to minimize the number of primitive operations that must be overridden in the child class while keeping common operations in the parent class.

  3. DOCUMENT the primitives that the child class is expected to override. Often this is done with the function name syntax.

EXAMPLE:
  1. java.awt.component's paint, update and repaint functions.

	Scott Herod


For Additional Information See Related Pages: SingletonPattern, StrategyPattern, TemplateMethodPattern, and BuilderPattern.

18th November 2002

We discussed Iterator, Visitor, and Flyweight.

Iterator

Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

Use an Iterator when you want to The Iterator pattern enables you to separate the responsibility for the access of the list from the responsibility for the traversal of the list. This increases the internal cohesion of the list class and of the classes that control the traversal of the list.

There may be several meaningful ways to traverse the list, and more that were not thought of when the list class was written. The list interface would become unmanageable if all possible traversal methods were to be built in to the list. Furthermore, it would be very difficult to have more than one traversal pending, as each traversal would need its own state.

An obvious example of this is the Iterator class in the Java Collections framework. Each subclass of list is free to return the most appropriate implementation of the Iterator interface.

This pattern is easy to describe, but has some interesting details.

In the example above the client asks the list for an iterator, and then calls methods of the iterator to traverse the list. GoF call this an external iterator. An alternative, called and internal iterator is for the client to pass give the list a callback object or function, and tell the iterator to traverse the list, triggering the callback for each element.

The next issue is who defines the traversal algorithm. If the iterator is responsible for this, then it must have knowledge of the internal structure of the list. This breaks encapsulation somewhat, but is the only practical way to define multiple traversal algorithms. The iterator may be made an inner class (or friend) of the list, and only expose its traversal methods in its public interface. This reduces external knowledge of the list's internals to just the iterator. An alternative is for the iterator only to maintain the current index in the list, and have a next() method on the list that moves forward. Consider a linked list. The iterator maintains a reference to the current item. When the client calls next() on the iterator, the iterator gets the next list item from the current item, sets its reference to the next item, and returns that item.

An iterator must address the situation where the list is modified during traversal. One solution is to make a copy of the list and traverse that. This may not be appropriate and is very inefficient. Another is to define this to be illegal and throw an exception as soon as it happens. To design a robust iterator requires that the list have some knowledge of the iterator, and update the iterator's internal state when the list changes.

RobJudd

Visitor Pattern

Let?s start with an example that has a class structure looks like one that depict below. The Modem interface contains all generic methods that all modems need implement.

The development team gets a new requirement to add a new functionality, which will configure the modem to work with the UNIX operating system.

The first idea comes to developer's mind is to add configureForUnix method in the interface so that client can call this method when the operating system is Unix. The immediate implication is that the developer need implement this method in all four derivatives of Modem interface. The diagram below shows the implementation. But, the problem of this implementation bring are:

1. The violation of OCP (Open Close Principle). The Modem interface would never be able to close.

2. The testing team has to retest all the functionality again, because of the change have been made to all the classes.

3. All Modem code has to be redeployed.

4. All works have to be repeated when supporting Window operating system and Mac come up.

Visitor Pattern Applied

Let?s apply the visitor pattern to this problem.

Notice the changes have been made in this class diagram. Please also pay attention to the real implementation of accept method.

GOF Visitor Pattern

Intent

Let you define a new operation without changing the classes of the elements on which it operates. Here is the UML model for GOF Visitor Pattern:

Please see the difference between the first visitor pattern and GOF visitor pattern. The implementation for the accept method is different.

There are two points I would like to make sure everyone aware of: 1. Client needs to have knowledge and creates the ConcreteVisitor? object.

2. Client needs to traverse the Element in object structure or object structure needs to provide the mechanism to traverse the Element and call the accept method on each individual Element within the object structure.

Applicability

1. An Object structure contains many classes of object with differing interfaces, and you want to perform operations on these objects that depend on their concrete classes.

2. Many distinct and unrelated operations need to be performed on objects in an object structure. And you want to avoid ?polluting? their classes with these operations.

3. The classes defining the object structure rarely change, but you often want to define new operations over the structure.

Consequences

1. Visitor makes adding new operations easy. Simply adding a new visitor.

2. A visitor related operations and separates unrelated ones.
     Related behavior is in the visitor instead spread them in the individual data object. Unrelated one is in the difference ConcreteVisitor?.

3. Adding new ConcreteElement? class is very hard, specially when there is bunch of visitor have already been defined. You need modify all specific visitor.

4. Visiting across class hierarchies. (The Element to be visited don?t have to be in the same class hierarchies.

5. Accumulating state. Visitors can accumulate states as they visit each element in the Object structure. Otherwise, the state has to be passed as a argument or a class instance variable

6. Breaking encapsulation. The ConcreteElement? has to provide the methods for visitor to use since it is in the different class hierarchies. As a result, the ConcreteElement? might need provided public/protected access to the element?s internal state, which might compromise its encapsulation.

Implementation Issues

1. Double-dispatch:
   This is the key for the visitor pattern. The operation that gets execusted depends on the type of Visitor and the type of the Element it visits. Consolidate the operations in a Visitor and use Accept to do the run-time binding.
2. Who is responsible for traversing the Object Structure? There is three possible ways to do this.

      *	In the Object Structure
Usually this is the good place to put it because encapsulate the object relationship within the Object Structure. Visitor does not have knowledge the implementation of relationship except the specific Element it visits.

      *	In the Iterator object (not understand the internal iterator and external iterator).
Internal is pretty much like case a. It will not have double-dispatch Single-dispatch: It calls an operation on the visitor with an element as an argument. Double-dispatch: it calls an operation on the element (accept) with the Visitor as an argument.

      * In the visitor.
The benefits for putting traverse code in the visitor is that you can change the way of traversing based on the result of operations on the object structure. (has a example)

Separating the data structure and operations that perform on the data structure into two different class hierarchies.

ACYCLIC VISITOR

Issues with the visitor pattern

1. Form Consequences, we know it is hard to add new derivative of Element.

2. The base class of the visited (Element) hierarchy depends on the base class of the visitor hierarchy (Visitor)

3. The base class of the visitor hierarchy has a function for each derivative of the visited hierarchy.

Cycle of dependencies that ties all the visited derivatives (all the Elements) together. The base class of the visitor base classes will have to be modified and recompiled along with all its derivatives every time a new derivatives is added to the visited hierarchy.

Solution

1. Create a degenerate visitor base class without any method. In Java, it is called the Marker Interface. In C++, only contains a pure virtual destructor.

2. Create a Specific visitor interface for each kind of visited derivative in the hierarchy. 3. The accept method in the visited hierarchy cast the visitor base class to the appropriate visitor interface.

Consequences

1. Visitor makes adding new operations easy Simply adding a new visitor.

2. A visitor related operations and separates unrelated ones
     Related behavior is in the visitor instead spread them in the individual data object. Unrelated one is in the difference ConcreteVisitor?.

3. Adding new ConcreteElement? class is relative easy By breaking the cycle dependency, adding a new ConcreteElement? is relative easy. You only needs to change required the visitor, and make incremental changes.

4. Visiting across class hierarchies (The Element to be visited don?t have to be in the same class hierarchies.

5. Accumulating state
   Visitors can accumulate states as they visit each element in the Object structure. Otherwise, the state has to be passed as a argument or a class instance variable 

6. Breaking encapsulation
      The ConcreteElement? has to provide the methods for visitor to use since it is in the different class hierarchies. As a result, the ConcreteElement? might need provided public/protected access to the element?s internal state, which might compromise its encapsulation.

7. The number of class is increased
      Each visited derivatives needs a visitor interface associated with

8. Needs to handle Exception condition and timing The accept method needs to handle exception which causes by class casting. It happens when the Specific Visitor did not implement the interface for this derivative. The casting might be impact by the width and breadth of the visited hierarchy

if you have any questions regrading the information posted here. please send email to Scott Miao, and he can be reached at Scott.Miao@level3.com

2th December 2002

We discussed Memento, Command, and Interpreter.

Command

Intent

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

Structure

Command ? interface for execute(), and unExecute() if undo is required.

ConcreteCommand ? implements execute; binds a receiver object with the action

Client ? creates the ConcreteCommand and sets the Receiver; may provide ConcreteCommands? for the Invoker.

Invoke ? invokes the command

Receiver ? knows how to carry out the command. Methods called by execute(). Any class can be the receiver. This pattern does not require that the Receiver implement any specific interface. Methods can vary from Receiver to Receiver.

Applicability:

  1. Object-oriented replacement for callbacks.

  2. If you want to queue commands, or execute at a different time.

  3. Supports undo (unExecute()).

  4. Supports logging.

  5. Command provides a way to model transactions.

Consequences:

  1. Decouples invoker object from the one that knows how to perform it (ConcreteCommand).

  2. Commands are first-class objects.

  3. Composite commands are possible. (Composite Pattern)

  4. Command interface is simple. New commands do not require you to change existing classes.

  5. Commands make it easy to have the same functionality in different places of the application. For example a GUI can have a menu item and a button that invoke the same ConcreteCommand.

Implementation:

  1. Command can vary as to how intelligent it is. It may not delegate to the receiver at all or it may delegate extensively.

  2. Undo/Redo issues ? you may have to store additional state, you may want a history list to support multiple levels of undo. Prototype pattern can be used to copy commands, if necessary.

  3. Hysteresis - Def. The lagging of an effect behind its cause, as when the change in magnetism of a body lags behind changes in the magnetic field. The problem is that errors can accumulate with multiple and repeated undo/redo. The Memento pattern can be used to store state.

  4. C++ templates ? Useful for simple commands, with no undo. Requires a consistent Receiver interface.

Other Examples

Related Patterns: CompositePattern, PrototypePattern, MementoPattern

See Also CommandPattern

-- SarahSmith

Interpreter

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

At first sight it seems a little hard to find uses for this pattern. The example in GoF is a regular expression matching interpreter which most of us either take for granted or do without. However, the first sentence of the motivation gives a clue as to how to use this pattern:

If a particular type of problem occurs often enough, then it might be worthwhile to express instances of the problem as sentences in a simple language.

Examples Warning: this pattern is not Parser. It specifically does not address the issue of parsing your sentence.

Method:

First define your grammar, and then construct a class hierarchy that describes your grammar. Each rule is a class; each symbol in the rule is an instance of the class.

Example: Graph Drawing

Suppose you are writing a graph drawing application. You want to graph simple functions such as y = 2x^2 + ln x + 1. This is a simple sentence in mathematics. The grammar may be described something like

 	 constant   ::= '0'|'1'| ... |'9'| {'0'|...|'9'}* |
 		        {'0'|...|'9'}*'.'{'0'|...|'9'}*
 	 variable   ::= 'x'
 	 add        ::= expression '+' expression
 	 subtract   ::= expression '-' expression
 	 multiply   ::= expression '*' expression
 	 divide     ::= expression '/' expression
 	 power      ::= expression '^' expression
 	 unary      ::= '-'expression | 'ln('expression')' |
                         'sin('expression')'|...|'function('expression')'
 	 expression ::= constant | variable | add | subtract | multiply |
 			divide | power | unary | '('expression')'

There are two types of expression class: those that represent terminal expressions (they hold no references to further expression classes) e.g. constant and variable, and non-terminal classes which are typically rules that represent compound expressions.

Classes representing the binary operators add, subtract, multiply, divide and power may be written as

     public class Addition extends AbstractExpression {
       private AbstractExpression left, right ;
       public Addition(AbstractExpression left,
 		       AbstractExpression right) {
 	this.left = left ;
 	this.right = right ;
       }
     }
while those representing unary expressions will be similar but take a single AbstractExpression?. Finally:

     public class Constant extends AbstractExpression {
       private double value ;
       public Constant(double value) {
 	this.value = value ;
       }
     }
and the class representing the variable has nothing in it so far.

     public class Variable extends AbstractExpression {
       public Variable() {}
     }
As mentioned above, the problem this pattern does not address is that of parsing sentences in the grammar. Specifically it provides no way to get from the equation y = 2 * x^2 + ln(x) + 1 to its class representation. This is someone else's problem. The class representation looks something like:

 		               Addition
 		       _________/    \_________
     	       	      /			       \          
           Multiplication     	       	      Addition
 	     / 	     \			        /    \ 
      Constant        Power 	  	  Logarithm  Constant
 		       	/ \		      |
 		       /   \		      |
 		      /	    \  	       	      |
 		Variable  Constant	  Variable
Where the lines represent is a member of.

Finally, we must implement an interpret method for each concrete subclass of AbstractExpression?. In this case we shall make interpret a member function of the concrete subclasses. It will take a double as its single parameter. The way the graph drawing program will use this structure is as follows. Suppose it wants to graph the equation above with the x-range from 0 to five, plotting points every 0.1. Then it would call interpret on the structure above for each value of x from 0 to 5 in intervals of 0.1. Let the top addition class be a field called function. The the program would do

	for (double x = 0; x<=5; x += 0.1) { 	   	  
	  double y = function.interpret(x) ; 	 	  
	  plot(x, y) ; 	 	
	}
Now, the interpret function is implemented as:

	public class Addition {
	  double interpret (double x) {
	    return left.interpret(x) + right.interpret(x) ;
	  }
	}

public class Logarithm { double interpret (double x) { return Math.log(expression.interpret(x)) ; } }

public class Constant { double interpret (double x) { return value ; } }

public class Variable { double interpret (double x) { return x ; } }
That's all there is to it!

Here are some consequences: Implementation details: See also InterpreterPattern

RobJudd


Observer

I expect most people are already familiar with the Observer pattern from using event listeners in Java. These are most common when writing user interfaces with widgets that need to respond to user input, but they apply more generally. The two most common situations where this pattern is appropriate are when The two participants are the Subject and the Observer. The Subject is the object being watched; it must know who is watching it so that it can notify the watchers when something has changed. It must provide an interface that allows observers to be added and removed. A single Subject may be watched by many Observers. The Observers define an interface that allows them to be notified of updates.

An example from Java is that of a List (which is the subject) that implements a list in a user interface, and an ItemListener (which is the Observer) that is interested in when items in the List are selected and deselected. The List provides the interface
    addItemListener(ItemListener)
    removeItemListener(ItemListener)
while ItemListener has the single method
    itemStateChanged(ItemEvent)
On the face of it this is a pretty simple pattern. However, there are some pitfalls to be aware of when implementing it.

4 February 2003

Fašade

Intent: Provide 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. Applicability Consequences Implementation Related Patterns Related Enterprise Fašade patterns: Interesting Comment RobertMartin, Agile Software Development: If you are following the ?Single Responsibility Principle?, you end up with lots of fine-grained classes. When the system becomes rigid and fragile, then you should refactor using the Fašade or Proxy pattern.

Articles Books other than GoF See FacadePattern

-- SarahSmith


BoulderPatternsGroup

EditText of this page (last edited August 17, 2005) or FindPage with title or text search