Design Pattern improvement catalog for MixJuice

Last updated: 2002-11-18 [Single page version] [Japanese version]

We have made a catalog of design pattern improvement achieved by MixJuice language. This catalog is useful not only for MixJuice programmers, but also AspectJ, CLOS and Ruby programmers. (See the section of For other programming languages for details.)

Here is a table that shows which kind of problems of each design pattern are resolved by the basic programming techniques of MixJuice. (We recommend you read Adapter, Decorator and Visitor.)

Improvements for Design Patterns by MixJuice
Design PatternI or AResolved problemsUsed Techniques
intrextinfotypecomp
AbstractFactoryIMabst-method-add
AMMNimpl-selection
BuilderIMNmethod-add
ANimpl-selection
FactoryMethodANNimpl-selection
PrototypeIMabst-method-add
SingletonAMmethod-ext
AdapterAMMinterface-add
BridgeINabst-method-add
ANNimpl-selection
Composite
DecoratorIMmethod-add, abst-method-add
AMMclass-ext
FacadeIMnamespace-sep
Flyweight
Proxy
ChainOfResponsibilityINMmethod-add, abst-method-add
Command
InterpreterINMabst-method-add
IteratorIMnamespace-sep
Mediator
MementoIMnamespace-sep
ObserverINclass-ext
StateINabst-method-add
StrategyANimpl-selection
TemplateMethod
VisitorI1Msep-spec-impl
I2NMabst-method-add
ANabst-method-add

Meanings of abbreviations:

I or A (See the section of An improvement of the solution or another solution for details):

I
Improvement of the GoF pattern
A
Another solution to the GoF pattern

Resolved problems (See the section of Categories of resolved problems for details):

intr
Introduction problem
ext
Extensibility problem
info
Information hiding problem
type
Type safety problem
comp
Complexity problem

Whether mentioned in the GoF book or not:

M
The resolved problem is mentioned in the GoF book.
N
The resolved problem is not mentioned in the GoF book.

Used Techniques (See the page of Programming techniques of MixJuice for details):

method-ext
method extension
class-ext
class extension
interface-add
interface addition
field-add
field addition
method-add
method addition
abst-method-add
abstract method addition
impl-selection
implementation selection
namespace-sep
namespace separation
sep-spec-impl
separation of specifications and implementations

An improvement of the solution or another solution

"I" means it is an improvement of the solution. MixJuice can resolve problems of GoF patterns without changing their class structure. In this case, all merits of GoF patterns are inherited to the improved solutions.

"A" means it is another solution whose class structure is different from the corresponding GoF pattern. There may be merits and demerits compared with the original GoF pattern.

Categories of resolved problems

Introduction problem

The original GoF pattern can not be introduced to the existing program without modifying the source code.

Extensibility problem

The original GoF pattern does not support some kind of extensions without modifying the source code.

Information hiding problem

The original GoF pattern forces some names to be public. (Some of these problems can be resolved by the package/nested-class mechanisms of Java.)

Type safety problem

The original GoF pattern requires downcast to a subclass in order to invoke the methods of the subclass.

Complexity problem

The class structure of the original GoF pattern is complicated and error prone.

Layered class diagram

Each solution in this catalog is explained using a "layered class diagram" and a pseudo code of MixJuice.

Layered class diagrams express how programs are extended by difference-based modules of MixJuice.

For more details, please see the proposal of layered class diagram.

About quotations from the GoF book

This catalog contains quoations from the GoF book, "Design Patterns", Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides.

"Intent" of each design pattern are directly quoted from the GoF book.

Each class diagram has been re-written to adapt to the recent notation of UML.

For other programming languages

Many of solutions in this catalog can be applicable to other AOP(aspect-oriented programming) or open-class languages, such as AspectJ, CLOS and Ruby.

Many of the programming techniques of MixJuice have corresponding programming techniques of such languages. Here is a table that shows correspondence between techniques of MixJuice and techniques of AspectJ, CLOS and Ruby.

Languages and Techniques
TechniquesAspectJCLOSRuby
method-extaround advicealias/def
interface-adddeclare parentsdefmethodinclude
field-addintroductionassignment
method-addintroductiondefmethoddynamic method definition
abst-method-addintroductionuseless because dynamic typing
namespace-sepaspectpackage
sep-spec-impl
impl-selectionaspect selectionrequire selection

Some documents of other languages and systems explains how they make some of Design Patterns unnecessary. See the following pages.

MixJuice home page

Aspect-Oriented Design Pattern Implementations

Their programming style is quite different from ours. They do not much use introduction feature; however, we use introduction only.

Contact

Comments are welcome. Plese send mail to <akr@m17n.org>.

Abstract Factory

Intent

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

Class diagram of the original GoF pattern

structure-GoF:abstractfactory

Improvement in MixJuice

Solved Problem(s)

Extensibility problem
In order to add new kinds of products, new creation methods should be added to AbstractFactory and ConcreteFactory classes. (This problem is mentioned at p.90,line.4-9 in the GoF book.)

Used programming technique(s)

Abstract method addition to AbstractFactory.

Consequences

Structure and pseudo code

structure:abstractfactory_sample1

module original {
  define abstract class AbstractFactory {
    define abstract AbstractProductA createProductA();
    define abstract AbstractProductB createProductB();
  }
  define class ConcreteFactory1 extends AbstractFactory {
    AbstractProductA createProductA(){...}
    AbstractProductB createProductB(){...}
  }
  define class ConcreteFactory2 extends AbstractFactory {
    AbstractProductA createProductA(){...}
    AbstractProductB createProductB(){...}
  }

  define abstract class AbstractProductA {...}
  define class ProductA1 extends AbstractProductA {...}
  define class ProductA2 extends AbstractProductA {...}

  define abstract class AbstractProductB {...}
  define class ProductB1 extends AbstractProductB {...}
  define class ProductB2 extends AbstractProductB {...}

  define class Client {
    AbstractFactory factory;
    define void m1(){
      AbstractProductA a = factory.createProductA();
      AbstractProductB b = factory.createProductB();
    }
  }
}
module extension extends original {
  class AbstractFactory {
    define abstract AbstractProductC createProductC();
  }
  class ConcreteFactory1 {
    AbstractProductC createProductC(){...}
  }
  class ConcreteFactory2 {
    AbstractProductC createProductC(){...}
  }

  define abstract class AbstractProductC {...}
  define class ProductC1 extends AbstractProductC {...}
  define class ProductC2 extends AbstractProductC {...}

  class Client {
    define void m2(){
      AbstractProductC c = factory.createProductC();
    }
  }
}

Another solution in MixJuice

Solved Problem(s)

Extensibility problem
In order to add new product, new creation method should be added to the Factory class. (This problem is mentioned at p.90,line.4-9 in the GoF book.)
Type safety problem
The original GoF pattern requires downcast from AbstractProduct to a concrete Product in order to invoke the specific methods of the Product. (This problem is mentioned at p.91,line27-40 in the GoF book.)
Complexity problem
The class structure of the original GoF pattern is complicated. (This problem is not mentioned in the GoF book.)

Used programming technique(s)

Implementation selection for Product classes.

Consequences

Structure and pseudo code

structure:abstractfactory_sample2

module products {
  define class ProductA {
    define abstract ProductA();
    ...
  }
  define class ProductB {
    define abstract ProductB();
    ...
  }
}

module products.implementation1 extends products {
  class ProductA {
    ProductA() {...}
    ...
  }
  class ProductB {
    ProductB() {...}
    ...
  }
}

module products.implementation2 extends products {
  class ProductA {
    ProductA() {...}
    ...
  }
  class ProductB {
    ProductB() {...}
    ...
  }
}

module client extends products {
  ... new ProductA() ...
  ... new ProductB() ...
}

Builder

Intent

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

Class diagram of the original GoF pattern

structure-GoF:builder

Improvement in MixJuice

Solved Problem(s)

Extensibility problem
Adding new methods to Builder and ConcreteBuilder classes is impossible without modifying the source code. (This problem is mentioned at p.100,line.32-p.101,line.4 in the GoF book.)

Used programming technique(s)

Method addition to Builder and ConcreteBuilder classes.

Consequences

Structure and pseudo code

structure:builder_sample1

module original {
 define abstract class Builder {
   define void buildPartA(){}
   define void buildPartB(){}
 }
 define class ConcreteBuilder extends Builder {
   void buildPartA(){...}
   void buildPartB(){...}
 }
 define class Director {
   Builder builder;
   define void construct(){
     builder.buildPartA();
     builder.buildPartB();
   }
 }
}
module extension extends original {
 class Builder {
   define void buildPartC(){}
 }
 define class ConcreteBuilder2 extends Builder {
   void buildPartA(){...}
   void buildPartB(){...}
   void buildPartC(){...}
 }
 class Director {
   void construct(){
     original();
     builder.buildPartC();
   }
 }
}

Another solution in MixJuice

Solved Problem(s)

Complexity problem
The class structure of the original GoF pattern is complicated.

Used programming technique(s)

Implementation selection for Builder.

Consequences

Structure and pseudo code

structure:builder_sample2

module builder {
  define class Builder {
    // This class has Director's function.
    define void construct() { ... }

    define void buildPartA() {}
    define void buildPartB() {}
    define void buildPartC() {}
  }
}

module builder.implementation1 extends builder {
  class Builder {
    void buildPartA() { ... }
    void buildPartB() { ... }
    void buildPartC() { ... }
  }
}

module builder.implementation2 extends builder {
  class Builder {
    void buildPartA() { ... }
    void buildPartB() { ... }
    void buildPartC() { ... }
  }
}

Factory Method

Intent

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

Class diagram of the original GoF pattern

structure-GoF:factorymethod

Another solution in MixJuice

Solved Problem(s)

Type safety problem
The original GoF pattern requires downcast from Product to a ConcreteProduct in order to invoke the specific methods of the ConcreteProduct. (This problem is not mentioned in the GoF book.)
Complexity problem
The class structure of the original GoF pattern is complicated. (This problem is mentioned at p.113,line.1-3 in the GoF book.)

Used programming technique(s)

Implementation selection for Product and Creator.

Consequences

Structure and pseudo code

structure:factorymethod_sample1

module m {
  define class Product {
    define abstract Product();
  }
  define class Creator {
    define Product product;
    define void anOperation() { ... product = new Product(); ... }
  }
}

module m.implementation extends m {
  class Product {
    Product() {...}
    define void concreteMethod() {...}
  }
  class Creator {
    define void anotherOperation() {
      ...
      product.concreteMethod(); // no need to cast.
      ...
    }
  }
}

Prototype

Intent

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

Class diagram of the original GoF pattern

structure-GoF:prototype

Improvement in MixJuice

Solved Problem(s)

Introduction problem
Original GoF pattern can not be introduced to the existing program without modifying the source code. (This problem is mentioned at p.120, line.37-39 in the GoF book.)

Used programming technique(s)

Abstract method addition of "copy()" method to the existing classes.

Consequences

Structure and pseudo code

structure:prototype_sample1

module original {
  define abstract class AbstractProduct {...}
  define class ConcreteProduct1 extends AbstractProduct {...}
  define class ConcreteProduct2 extends AbstractProduct {...}
}

module extension extends original {
  class AbstractProduct {
    define abstract AbstractProduct copy();
  }

  class ConcreteProduct1 {
    AbstractProduct copy() {...}
  }

  class ConcreteProduct2 {
    AbstractProduct copy() {...}
  }
}

Singleton

Intent

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

Class diagram of the original GoF pattern

structure-GoF:singleton

Another solution in MixJuice

Solved Problem(s)

Complexity problem
The original GoF pattern is complicated and error prone. (Although this problem is not mentioned in the GoF book, the demerits of static methods are mentioned at p.128, line.14-16 that implies static methods are preferable if these demerits do not matter.)

Used programming technique(s)

Method extension of static methods solve the problem of static methods, limitation of extensibility. (Note that the current version of MixJuice, version 1.0, does not support method extension of static methods; however the future version will support it.)

Consequences

Structure and pseudo code

structure:singleton_sample1

module original {
  define class C {
    define static void operation() {...}
    define static int data;
  }
}

module extension extends original {
  class C {
    static void operation() { ... original() ...}
  }
}

Adapter

Intent

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

Class diagram of the original GoF pattern

Class adapter

structure-GoF:adapter1

Object adapter

structure-GoF:adapter2

Another solution in MixJuice

Solved Problem(s)

Extensibility problem
Object adapters make it impossible to override Adaptee behavior without modifying the source code of Adapter. It requires new subclass SubAdaptee and modifying Adapter so that it create an instance of SubAdaptee instead of Adaptee. (This problem is mentioned at p.142 lines 14-16 in the GoF book.)
Complexity problem
In order to adapt a class and all its subclasses using class adapters, each class to be adapted requires corresponding class adapter. (This problem is mentioned at p.140 lines 24-26 and p.143 lines 9-12 in the GoF book.)

Used programming technique(s)

Super-interface addition to Adaptee class.

Consequences

The followings are trade-offs between class adapters, object adapters and this solution. (See also p.142 in the GoF book that explains trade-offs between class and object adapters.)

Structure and pseudo code

structure:adapter_sample1

module library {
  define class Adaptee {
    define void specificRequest() {...}
  }
  define class SubAdaptee extends Adaptee {...}
}
module application extends library {
  define interface Target {
    define void request();
  }
  class Adaptee implements Target {
    void request() { specificRequest(); }
  }
}

Bridge

Intent

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

Class diagram of the original GoF pattern

structure-GoF:bridge

Improvement in MixJuice

Solved Problem(s)

Extensibility problem
It is impossible to add new operations to Abstraction and Implementor without modifying the source code. (This problem is not mentioned in the GoF book.)

Used programming technique(s)

Abstract method addition to Abstraction and Implementor.

Consequences

Structure and pseudo code

structure:bridge_sample1

module original {
  define abstract class Abstraction {
    Implementor imp;
    define void operation() { imp.operationImp(); }
  }

  define class RefinedAbstraction extends Abstraction {
    ...
  }

  define abstract class Implementor {
    define abstract void operationImp();
  }

  define class ConcreteImplementorA extends Implementor {
    void operationImp() { ... }
  }

  define class ConcreteImplementorB extends Implementor {
    void operationImp() { ... }
  }
}

module extension extends original {
  class Abstraction {
    define void operation2() { imp.operationImp2(); }
  }

  class Implementor {
    define abstract void operationImp2();
  }

  class ConcreteImplementorA {
    void operationImp2() { ... }
  }

  class ConcreteImplementorB {
    void operationImp2() { ... }
  }
}

Another solution in MixJuice

Solved Problem(s)

Type safety problem
The original GoF pattern requires downcast from Implementor to a ConcreteImplementor in order to invoke the specific methods of the ConcreteImplementor. (This problem is not mentioned in the GoF book.)
Complexity problem
The class structure of the original GoF pattern is complicated. (This problem is not mentioned in the GoF book.)

Used programming technique(s)

Implementation selection of Abstraction.

Consequences

+ Downcasts are no longer needed. - This solution is applicable only if just one implementation of Abstraction is used in a program.

Structure and pseudo code

structure:bridge_sample2

module original {
  define class Abstraction {
    define void operation() {
      ... implementationOperation1(); ...
    }

    define abstract void implementationOperation1();
    define abstract void implementationOperation2();
  }

  define class RefinedAbstractionA extends Abstraction {...}
  define class RefinedAbstractionB extends Abstraction {...}
}

module implementation1 extends original {
  class Abstraction {
    void implementationOperation1() {...}
    void implementationOperation2() {...}
  }
}

module implementation2 extends original {
  class Abstraction {
    void implementationOperation1() {...}
    void implementationOperation2() {...}
  }
}

Composite

No significant improvement have been found.

Decorator

Intent

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

Class diagram of the original GoF pattern

structure-GoF:decorator

Improvement in MixJuice

Solved Problem(s)

Extensibility problem
It is impossible to add new method to Component and Decorator without modifying the source code. (This problem is mentioned at p.179,line.3-5 in the GoF book.)

Used programming technique(s)

Method addition or abstract method addition to Component and Decorator.

Consequences

Structure and pseudo code

structure:decorator_sample1

module original {
  define abstract class Component {
    define abstract void operation();
  }
  define class ConcreteComponent extends Component {
    void operation(){...}
  }
  define abstract class Decorator extends Component {
    Component component;
    void operation(){ component.operation(); }
  }
  define class ConcreteDecorator extends Decorator {
    void operation(){...}
  }
}
module extension extends original {
  class Component {
    define abstract void newOperation();
  }
  class ConcreteComponent {
    void newOperation(){...}
  }
  class Decorator {
    void newOperation(){ component.newOperation(); }
  }
}

Another solution in MixJuice

Solved Problem(s)

Extensibility problem
It is impossible to add new method to Component and Decorator without modifying the source code. (This problem is mentioned at p.179,line.3-5 in the GoF book.)
Complexity problem
A decorator and its component aren't identical. (This problem is mentioned at p.178,line.29-32 in the GoF book.) Lots of little objects. (This problem is mentioned at p.178,line.33-37 in the GoF book.)

Used programming technique(s)

Class extension for Component.

Consequences

Structure and pseudo code

structure:decorator_sample2

module original {
  define class Component {
    define void operation();
  }
}
module extension1 extends original {
  class Component {
    void operation(){...}
  }
}
module extension2 extends original {
  class Component {
    void operation(){...}
  }
}

Facade

Intent

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

Class diagram of the original GoF pattern

structure-GoF:facade

Improvement in MixJuice

Solved Problem(s)

Information hiding problem
Hiding of subsystem classes from clients is not supported by OLD object-oriented languages. (This problem is mentioned at p.188,line.33-37 in the GoF book.)

Used programming technique(s)

Namespace separation.

Consequences

Structure and pseudo code

structure:facade_sample1

module subsystem {
  define class C1 { ...  }
  define class C2 { ...  }
  ...
}

module facade {
  define class Facade {
    define abstract void easy_operation();
  }
}

module facade.implementation extends facade, subsystem {
  class Facade {
    void easy_operation() { ... }
  }
}

Flyweight

No significant improvement have been found.

Proxy

No significant improvement have been found.

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.

Class diagram of the original GoF pattern

structure-GoF:chain

Improvement in MixJuice

Solved Problem(s)

Introduction problem
It is impossible to introduce Chain of Responsibility pattern into the existing classes without modifying the source code. (This problem is not mentioned in the GoF book.)
Extensibility problem
It is impossible to add new operations to Handler without modifying the source code. (This problem is mentioned at p.227,line.20-23 in the GoF book.)

Used programming technique(s)

Method addition to Handler and ConcreteHandler classes.

Consequences

Structure and pseudo code

structure:chain_sample1

module original {
  define abstract class Handler {
    Handler successor;
    define void handleRequestA(){ successor.handleRequestA(); }
  }

  define class ConcreteHandler1 extends Handler {
    void handleRequestA() {...}
  }

  define class ConcreteHandler2 extends Handler {
    void handleRequestA() {...}
  }
}

module extension extends original {
  class Handler {
    define void handleRequestB(){ successor.handleRequestB(); }
  }

  class ConcreteHandler1 {
    void handleRequestB() {...}
  }

  class ConcreteHandler2 {
    void handleRequestB() {...}
  }
}

Command

No significant improvement have been found.

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.

Class diagram of the original GoF pattern

structure-GoF:interpreter

Improvement in MixJuice

Solved Problem(s)

Introduction problem
It is impossible to introduce Interpreter pattern into existing tree structure without modifying the source code. (This problem is not mentioned in the GoF book.)
Extensibility problem
It is impossible to add new ways to interpret expressions without modifying the source code. (This problem is mentioned at p.247,line.11-16 in the GoF book.)

Used programming technique(s)

Abstract method addition to AbstractExpression.

Consequences

Structure and pseudo code

structure:interpreter_sample1

module original {
  define class Client {
    AbstractExpression exp;
    Context context;
    define void m(){
      exp.interpret(context);
    }
  }
  define class Context {...}
  define abstract class AbstractExpression {
    define abstract void interpret(Context context);
  }
  define class ExpressionA extends AbstractExpression {
    void interpret(Context context){...}
  }
  define class ExpressionB extends AbstractExpression {
    void interpret(Context context){...}
  }
}
module extension extends original {
  class AbstractExpression {
    define abstract void newOperation();
  }
  class ExpressionA {
    void newOperation(){...}
  }
  class ExpressionB {
    void newOperation(){...}
  }
}

Iterator

Intent

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

Class diagram of the original GoF pattern

structure-GoF:iterator

Improvement in MixJuice

Solved Problem(s)

Information hiding problem
Internal state of Aggregate should be accessible from Iterator but hidden from clients. (This problem is mentioned at p.262,line.18-23 in the GoF book.) Note that this problem is also solved by the package/nested-class mechanisms of Java.

Used programming technique(s)

Namespace separation of ConcreteAggregate and ConcreteIterator.

Consequences

Structure and pseudo code

structure:iterator_sample1

module aggregate {
  define class Aggregate {
    define abstract Iterator createIterator();
  }

  define class Iterator {
    define abstract void first();
    define abstract void next();
    define abstract boolean isDone();
    define abstract Object currentItem();
  }

  define class ConcreteAggregate extends Aggregate {
  }
  define class ConcreteIterator extends Iterator {
  }
}

module aggregate.implementation extends aggregate {
  class ConcreteAggregate {
    Iterator createIterator() {...}
  }
  class ConcreteIterator {
    // accessible to ConcreteAggregate directly.
    void first() {...}
    void next() {...}
    boolean isDone() {...}
    Object currentItem() {...}
  }
}

Mediator

No significant improvement have been found.

Memento

Intent

Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored to this state later.

Class diagram of the original GoF pattern

structure-GoF:memento

Improvement in MixJuice:

Solved Problem(s)

Information hiding problem
Internal state of Memento should be accessible from Originator but hidden from clients. (This problem is mentioned at p.286,line.25-26 in the GoF book.) Note that this problem is also solved by the package/nested-class mechanisms of Java.

Used programming technique(s)

Namespace separation of Memento.

Consequences

Structure and pseudo code

structure:memento_sample1

module m {
  define class Originator {
    define abstract void setMemento(Memento m);
    define abstract Memento createMemento();
  }

  define class Memento {}
}

module m.implementation extends m {
  class Originator {
    int state;
    void setMemento(Memento m) {...}
    Memento createMemento() {...}
  }

  class Memento {
    int state;
  }
}

Observer

Intent

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

Class diagram of the original GoF pattern

structure-GoF:observer

Improvement in MixJuice

Solved Problem(s)

Introduction problem
It is impossible to introduce Observer pattern into the existing program without modifying the source code. (This problem is not mentioned in the GoF book.)

Used programming technique(s)

Class extension for Subject.

Consequences

Structure and pseudo code

structure:observer_sample1

module original {
  define class Subject {
    define void sideEffectOperation() {...}
  }
}

module extension extends original {
  define abstract class Observer {
    define abstract void update();
  }

  class Subject {
    define void attach(Observer o) {...}
    define void detach(Observer o) {...}
    define void changed() {...}

    void sideEffectOperation() {
      original();
      changed();
    }
  }
}

State

Intent

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

Class diagram of the original GoF pattern

structure-GoF:state

Improvement in MixJuice

Solved Problem(s)

Extensibility problem
It is impossible to add new operation to State without modifying the source code. (This problem is not mentioned in the GoF book.)

Used programming technique(s)

Abstract method addition to State.

Consequences

Structure and pseudo code

structure:state_sample1

module original {
  define class Context {
    State state;
    define void request(){
      state.handle();
    }
  }
  define abstract class State {
    define abstract void handle();
  }
  define class ConcreteStateA extends State {
    void handle(){...}
  }
  define class ConcreteStateB extends State {
    void handle(){...}
  }
}
module extension extends original {
  class State {
    define abstract void newOperation();
  }
  class ConcreteStateA {
    void newOperation(){...}
  }
  class ConcreteStateB {
    void newOperation(){...}
  }
}

Strategy

Intent

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

Class diagram of the original GoF pattern

structure-GoF:strategy

Another solution in MixJuice

Solved Problem(s)

Complexity problem
The class structure of the original GoF pattern is complicated. (This problem is not mentioned in the GoF book.)

Used programming technique(s)

Implementation selection for Context.

Consequences

Structure and pseudo code

structure:strategy_sample1

module m {
  define class C {
    define void contextInterface() {
      ... algorithmInterface() ...
    }
    define abstract void algorithmInterface();
  }
}
module m.strategyA extends m {
  class C { void algorithmInterface() {...} }
}
module m.strategyB extends m {
  class C { void algorithmInterface() {...} }
}

Template Method

No significant improvement have been found.

Visitor

Intent

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

Class diagram of the original GoF pattern

structure-GoF:visitor

Improvement in MixJuice (1)

Solved Problem(s)

Information hiding problem
The fields of object structure tends to be public. (This problem is mentioned at p.337, line.1-4 in the GoF book.)

Used programming technique(s)

Separation of specifications and implementations of ConcreteElement classes. (This improvement is applicable also to another solution described below.)

Consequences

Structure and pseudo code

structure:visitor_sample1

module element {
  define abstract class Element {
    define abstract void accept(Visitor visitor);
  }
  define class ConcreteElementA extends Element {
    void accept(Visitor v){ v.visitConcreteElementA(this); }
  }
  define class ConcreteElementB extends Element {
    void accept(Visitor v){ v.visitConcreteElementB(this); }
  }
  define abstract class Visitor {
    define abstract void visitConcreteElementA(ConcreteElementA a);
    define abstract void visitConcreteElementB(ConcreteElementB a);
  }
}
module element.implementation extends element {
  class ConcreteElementA {
    int state;
  }
  class ConcreteElementB {
    int state;
  }
}
module visitor extends element {
  define class ConcreteVisitor extends Visitor {}
}
module visitor.implementation
  extends visitor, element.implementation {
  class ConcreteVisitor {
    void visitConcreteElementA(ConcreteElementA a){
      ... int x = a.state; ...
    }
    void visitConcreteElementB(ConcreteElementB b){
      ... int x = b.state; ...
    }
  }
}

Improvement in MixJuice (2)

Solved Problem(s)

Introduction problem
Introducing Visitor pattern to existing object structure is impossible without modifying the source code of object structure. (This problem is not mentioned in the GoF book.)
Extensibility problem
Adding new ConcreteElement classes is impossible without modifying the source code of Visitor and ConcreteVisitor classes. (This problem is mentioned at p.336, line.4-17 in the GoF book.)

Used programming technique(s)

Abstract method addition to Element and ConcreteElement classes solves the introductionability problem. Abstract method addition to Visitor and ConcreteVisitor classes solves the extensibility problem.

Consequences

Structure and pseudo code

structure:visitor_sample2

module element {
  define abstract class Element {...}
  define class ConcreteElementA extends Element {...}
  define class ConcreteElementB extends Element {...}
}

module visitor extends element {
  class Element { define abstract void accept(Visitor v); }
  class ConcreteElementA { void accept(Visitor v) { v.visit(this); } }
  class ConcreteElementB { void accept(Visitor v) { v.visit(this); } }

  define class Visitor {
    define abstract void visit(ConcreteElementA elt);
    define abstract void visit(ConcreteElementB elt);
  }

  define class ConcreteVisitor1 extends Visitor {
    void visit(ConcreteElementA elt) {...}
    void visit(ConcreteElementB elt) {...}
  }

  define class ConcreteVisitor1a extends ConcreteVisitor1 {
    void visit(ConcreteElementA elt) {...}
    void visit(ConcreteElementB elt) {...}
  }
}

module new_concrete_element extends visitor {
  define class ConcreteElementC extends Element {
    ...
    void accept(Visitor v) { v.visit(this); }
  }

  class Visitor {
    define abstract void visit(ConcreteElementC elt);
  }

  class ConcreteVisitor1 {
    void visit(ConcreteElementC elt) {...}
  }

  class ConcreteVisitor1a {
    void visit(ConcreteElementC elt) {...}
  }
}

Another solution in MixJuice:

Solved Problem(s)

Complexity problem
The class structure of Visitor pattern is complicated and error prone. (This problem is not mentioned in the GoF book.)

Used programming technique(s)

Abstract method addition to the existing object structure.

Consequences

Structure and pseudo code

structure:visitor_sample3

module element {
  define abstract class Element {...}
  define class ConcreteElementA extends Element {...}
  define class ConcreteElementB extends Element {...}
}

module traverser extends element {
  class Element { define abstract void traverse(); }
  class ConcreteElementA { void traverse() {...} }
  class ConcreteElementB { void traverse() {...} }
}

Akira TANAKA <akr@m17n.org>, Yuuji ICHISUGI <y-ichisugi@aist.go.jp>

Top