Introduction

Design patterns are elegant solutions to recurring problems in software design.

Archive for the ‘Design Patterns’ Category

Friday, May 19th, 2006

Dependency Injection

cheap cialis pill certified cialis cheap viagra in canada cialis buy drug buy generic cialis viagra buy 25mg viagra cheap viagra without prescription buy cheapest viagra on line purchase viagra cialis 10mg buying generic viagra cialis pills viagra from india cheapest sildenafil citrate cheap cialis no rx viagra india cialis bangkok viagra for order buy sildenafil internet buy generic viagra online buying cialis online where to order cialis tablet cialis find cialis no prescription required viagra cheap drug order cialis cheap online online pharmacy cialis cialis no rx order generic cialis price of cialis viagra soft drug viagra cheap viagra from uk order cialis no prescription order cheap viagra viagra drug order cheap cialis cheap cialis pharmacy best price for viagra cheap viagra from usa cost cialis cialis overnight shipping cheapest generic cialis online generic viagra online online viagra viagra sales cheap cialis in canada compare cialis prices online cialis online drug viagra online purchase discount cialis without prescription no rx viagra cialis overnight viagra uk cialis order cheap cialis from usa buying cialis cialis overnight delivery cialis in bangkok buy and purchase sildenafil online impotence treatment cheap price viagra viagra sale cheap cialis tablet drug cialis generic cialis online cheap viagra pharmacy find discount cialis online viagra malaysia cialis without a prescription buy cialis online cheap viagra rx buy no rx viagra cialis 20mg viagra in malaysia discount viagra online buy sildenafil cheap buy viagra low price buy cialis cialis cheap price cialis cheap generic viagra cialis canada low cost viagra buy cheap viagra cialis vs viagra order cialis from us cialis tablets find no rx cialis buy generic cialis online buy viagra overnight delivery cheapest cialis price buy cheapest cialis on line order cialis in canada viagra tablet viagra no online prescription find cheap cialis online viagra price order viagra no prescription cheap generic cialis buy viagra online cheap cialis uk cialis without rx generic cialis cheap viagra vs cialis order cialis on internet viagra tablets viagra purchase impotence drugs buy cialis generic cialis tablet cialis cheapest price order viagra from canada viagra generic cheap viagra from canada order cialis compare viagra prices online find cheap cialis impotence cure pfizer viagra find discount cialis cheapest cialis buy cialis from india impotence buy cheapest viagra online cialis side effects viagra order discount cialis online cialis in malaysia cialis in uk viagra in uk cialis online without prescription cialis online pharmacy order viagra buy viagra online viagra side effects cialis sale discount cialis no rx cheapest viagra find cialis order cialis no rx buy cialis low price buy viagra cheap drug cialis online purchase order discount viagra online 50 mg viagra 100 mg viagra 10mg cialis cost of cialis cheapest cialis prices buy discount viagra online cialis sales 50mg viagra cialis price buy viagra on internet cialis pill cheapest cialis online purchase viagra overnight delivery cheap cialis from canada cheapest viagra price cialis 20 mg buy sildenafil low cost order viagra without prescription buy viagra lowest price no prescription cialis order viagra on internet discount cialis overnight delivery cialis cheap drug viagra approved viagra no rx required compare viagra prices no rx cialis cheap cialis on internet buy viagra from india buy discount cialis online viagra pharmacy online order viagra from us cialis free delivery cialis for order buy cialis from canada viagra without rx viagra online review 10 mg cialis cheap viagra no rx cheapest viagra prices viagra prices cialis pharmacy order no rx cialis buy cialis in us buy cialis no prescription required order cialis from canada lowest price cialis cheap cialis internet online pharmacy viagra cheapest generic cialis generic drugs cialis india find cialis without prescription best price cialis buy viagra without prescription cheap cialis in uk where to buy viagra 20 mg cialis cheap cialis from uk buy sildenafil canada cialis no rx required cialis in us buy cialis overnight delivery cialis cheap price order cheap viagra online 20mg cialis buy cheap viagra online viagra internet viagra without prescription free cialis buy cialis us cialis buy buy viagra in canada order viagra cheap online find viagra without prescription viagra pills cheap cialis no prescription viagra online without prescription order generic viagra cialis discount viagra cheapest price purchase viagra no rx viagra no rx viagra cheap discount viagra overnight delivery sale cialis cialis pharmacy online purchase cialis without prescription pharmacy online cialis medication discount viagra buy cheap cialis impotence medication viagra medication find cialis on internet impotence pills cialis prices discount viagra without prescription cialis online cheap cialis online review find cheap viagra online buy viagra us purchase cialis online certified viagra where to order viagra buy cheapest viagra buy cialis internet order cialis online buy sildenafil online buy cialis cheap cheap viagra purchase cialis find discount viagra buy cialis on internet cialis buy online buy sildenafil online without a prescription viagra buy online order cheap cialis online viagra information no prescription viagra cost of viagra buy cialis in canada buy cialis online buy viagra cheapest generic viagra cialis us cialis australia fda approved cialis lowest price for viagra viagra bangkok cialis prescription cialis cost buy no rx cialis buy viagra internet viagra discount order viagra overnight delivery generic cialis viagra australia 25 mg viagra order viagra online viagra overnight cialis rx order cialis in us order viagra no rx order discount cialis online viagra vendors order viagra in us buy sildenafil in uk viagra us buy generic viagra viagra canada viagra no prescription viagra cheap price cheap viagra tablet viagra free delivery overnight viagra purchase viagra online find cheap viagra cialis malaysia best price viagra cialis free sample find viagra on internet cialis generic buy sildenafil in canada order cialis no prescription required cheapest viagra online purchase cialis no rx viagra in us order discount cialis cheap viagra internet free viagra cialis approved best price for cialis cialis from india find no rx viagra generic viagra viagra from canada viagra online pharmacy buy viagra from canada cheapest generic viagra online buy cheapest cialis discount cialis viagra overnight delivery cialis without prescription 100mg viagra cialis in australia price of viagra order cialis overnight delivery cheap viagra in uk buying generic cialis viagra pill buy cialis on line low cost cialis find discount viagra online buying viagra cheap cialis overnight delivery pharmacy cialis cheap viagra pill viagra prescription find viagra online buy cialis lowest price discount viagra no rx online cialis viagra free sample cheap viagra in usa find viagra cheap viagra online buy viagra no rx generic viagra cheap buy cialis without prescription buy viagra in us cheap viagra overnight delivery cheap cialis in usa cheap cialis online viagra order no rx viagra viagra soft tab find cialis online lowest price viagra cialis drug cialis vendors viagra online stores erectile dysfunction order viagra in canada buy viagra on line viagra overnight shipping viagra online cheap lowest price for cialis approved viagra pharmacy cialis 10 mg cialis no online prescription cialis purchase cialis from canada order cialis without prescription viagra for sale viagra in australia approved cialis pharmacy buy viagra generic buy sildenafil in spain find viagra no prescription required cialis no prescription buy viagra from us order viagra no prescription required cost viagra purchase viagra without prescription buy cialis no rx cialis cheap cialis internet tablet viagra cheap viagra on internet viagra cost pharmacy viagra cialis soft tab cialis information buy cheap cialis internet purchase cialis overnight delivery cheap cialis without prescription buy viagra no prescription required compare cialis prices buy cheap cialis online overnight cialis where to buy cialis cheap cialis buy cheap viagra internet buy discount cialis viagra buy drug cheap viagra no prescription buy sildenafil citrate buying viagra online buy discount viagra fda approved viagra cialis online stores cheap cialis tablets buy cheapest cialis online cheap viagra tablets order discount viagra sale viagra viagra online cialis for sale cialis soft viagra pharmacy buy cialis from us viagra without a prescription viagra in bangkok

Applications consist of multiple classes which collaborate with each other. For example an instance of class A needs an instance of class B and C to do its job; in other words, class A depends on class B and C; class B and C are thus dependencies of class A.

There are three options to satisfy dependencies:

  1. hard-code dependencies,
  2. look up dependencies,
  3. use the Dependency Injection pattern.

1. Hard-coding dependencies is the easiest strategy: class A simply instantiates its dependencies.

  1. class A {
  2.    
  3.     private var b:B;
  4.     private var c:C;
  5.    
  6.     public function A() {
  7.         b = new B(3, true);
  8.         c = new C();
  9.     }
  10.    
  11.     public function doSomething() {
  12.         var r:String = b.doSomething();
  13.         c.doSomething(r);
  14.     }
  15.    
  16. }

Problems of hard-coding dependencies:

  • Configuration is distributed across the whole application (configuration is in this case wiring up the instances and configuring dependent instances).
  • Class A must be modified to exchange a dependency (tight coupling): the instance of B may be replaced by an instance of SubB which fulfils the same contract as its super-class B. If B were an interface than any implementations could be used to satisfy the dependency.
  • What if a fourth class D has a dependency to the same instance of B as class A?

2. Looking up dependencies requires a context: class A gets the context and looks up its dependencies.

  1. class A {
  2.    
  3.     private var b:B;
  4.     private var c:C;
  5.    
  6.     public function A() {
  7.         var context:Context = Context.getInstance();
  8.         b = context.getB();
  9.         c = context.getC();
  10.     }
  11.    
  12.     …
  13.    
  14. }

Advantages of looking up dependencies:

  • Partially centralized configuration of the context: dependency b is already fully configured; but every instance looks up its dependencies on its own.
  • One instance can be used to satisfy multiple dependencies: an instance of class D can simply use context.getB() to get the same instance.

Problems of looking up dependencies:

  • Class A depends on a context: makes unit testing more difficult and the look ups are disturbing.
  • Code is bloated with dependency look-ups.

3. Using the Dependency Injection pattern is simple and places no requirements: class A provides ways to inject dependencies.

Advantages of dependency injection:

  • Configuration is centralized in one place: both configuration of instances and wiring up instances.
  • Dependencies can be exchanged easily (loose coupling).
  • Wiring up instances is made easy.

Problem of dependency injection: The wiring code may become rather complex if there are a lot of instances with a lot of dependencies to satisfy.

One way to go is to use Constructor Injection. In this approach class A declares a constructor with paramters for both dependencies; the dependencies are given on instantiation.

  1. class A {
  2.    
  3.     private var b:B;
  4.     private var c:C;
  5.    
  6.     public function A(b:B, c:C) {
  7.         this.b = b;
  8.         this.c = c;
  9.     }
  10.    
  11.     …
  12.    
  13. }

Advantages of constructor injection:

  • Dependencies cannot be changed after instantiation.
  • Initialization which requires all dependencies can be done directly in the constructor.
  • Instance is not in illegal state after instantiation.

Problems of constructor injection:

  • Parameter list of constructor may become very long (there may be a lot of dependencies, plus other information to pass to the constructor).
  • Parameters are distinguished by index and not by name, which may make the code harder to understand.

Another way to go is Setter Injection. In this approach class A provides setters for both dependencies; the dependencies are satisfied after instantiation.

  1. class A {
  2.    
  3.     private var b:B;
  4.     private var c:C;
  5.    
  6.     public function A() {
  7.     }
  8.    
  9.     public function setB(b:B):Void {
  10.         this.b = b;
  11.     }
  12.    
  13.     public function setC(c:C):Void {
  14.         this.c = c;
  15.     }
  16.    
  17.     …
  18.    
  19. }

Advantages of setter injection:

  • Constructor can be used to pass other information than dependencies.
  • Code is easier to understand because names rather than indices are used to distinguish dependencies.

Problems of setter injection:

  • Dependencies may not have been satisfied when needed.
  • Dependencies may be changed after ‘official’ initialization.
  • Initialization may have to be done after all dependencies are satisfied: init-method is needed.

While dependency injection is a pattern with many advantages, there are also some problems when used extensively, which can only be solved by an Inversion of Control Container. Such a container provides means of managing instances: lifecycle management (instantiating classes, setting dependencies, invoking init-methods, destroying classes), looking up managed instances, configuring managed instances, resolving dependencies.

In my following articles I’m going to present the As2lib Inversion of Control Container and show you how it solves the problems mentioned above and which other functionalities it provides (for example using its generic XML dialect to create UIs with ActionStep, AsWing, EnFlash or any other component library).

Further Reading: Inversion of Control Containers and the Dependency Injection pattern

Saturday, June 19th, 2004

DP: Singleton

A thread about the Singleton Design Pattern arised in the Flashforum (German). We (Nico Zimmermann, Ralf Bokelberg, Florian Kruesch and myself) discussed different implementations of the Singleton Pattern and what the advantages and disadvantages of each are. All started very basic with the simplest implementation all of you probably know.

  1. /**
  2. * Singleton shows a basic implementation of the Singleton Design
  3. * Pattern.
  4. *
  5. * @author Simon Wacker
  6. */
  7. class org.swacker.designpattern.Singleton {
  8.   /** Stores the onliest instance existing of this class. */
  9.   private static var instance:Singleton;
  10.  
  11.   /**
  12.    * Private constructor to prevent instantiation from outside of
  13.    * this class.
  14.    */
  15.   private function Singleton(Void) {
  16.   }
  17.  
  18.   /**
  19.    * Returns the onliest existing instance of this class.
  20.    *
  21.    * @return the onliest instance of this class
  22.    */
  23.   public static function getInstance(Void):Singleton {
  24.     // creates a new instance of this class if none exists
  25.     if (!instance) instance = new Singleton();
  26.     // returns the stored instance
  27.     return instance;
  28.   }
  29. }

Then we thought about the problems that emerge using this kind of implementation.
The first problem is that it is awkward to substitute the currently used Singleton with a new one. You had to change ALL references.
The second and maybe not that obvious issue is that only one instance of the Singleton class can exist in the whole project.
You probably think: Why should that be a problem? Doesn’t it lie in the nature of a Singleton that only one instance can exist of it?
These two statements are probably right BUT you normally want to have one instance of the Singleton in one context and not only one in a whole project. Thus my definition of a Singleton would be the following: A Singleton is a class that has exactly one instance in one context. This instance is shared among all classes in that context.
This definition sadly conflicts with the one of GoF (Gang of Four): Ensure a class only has one instance, and provide a global point of access to it.
But I think that the variation is acceptable. My definition maybe reminds you more of the Multiton Design Pattern.
So, how would one implement such a context spcific Singleton. That’s rather easy. You just have to use a factory that decides which instance to instantiate and whether to store this instance for sharing, thus making it a Singleton. You must store the instance of a specific factory global to one context.

  1. /**
  2. * Singleton is just representing any normal class. It does not have
  3. * any specific features.
  4. *
  5. * @author Simon Wacker
  6. */
  7. class org.swacker.designpattern.Singleton {
  8.   /**
  9.    * Constructs a new Singleton instance.
  10.    */
  11.   public function Singleton(Void) {
  12.   }
  13. }
  1. /**
  2. * SingletonFactory is a factory that always returns the same instance
  3. * when #getSingleton() is called. This instance thus gets shared among
  4. * all referencing classes in the factory’s context. At least if an
  5. * instance of the specific class gets obtained via SingletonFactory#getSingleton().
  6. *
  7. * @author Simon Wacker
  8. */
  9. class org.swacker.designpattern.SingletonFactory {
  10.   /** The shared instance of the Singleton. */
  11.   private var singleton:Singleton;
  12.  
  13.   /**
  14.    * Constructs a new SingletonFactory.
  15.    */
  16.   public function SingletonFactory(Void) {
  17.   }
  18.  
  19.   /**
  20.    * Returns the instance stored in the instance variable ’singleton’.
  21.    *
  22.    * @return the Singleton instance shared among all referencing classes
  23.    */
  24.   public function getSingleton(Void):Singleton {
  25.     if (!singleton) singleton = new Singleton();
  26.     return singleton;
  27.   }
  28. }

As you can see, what we have done is moving the storing mechanism out of the Singleton and into the SingletonFactory. In our case the class that gets instantiated by the SingletonFactory is hard-coded. We could create a dynamic SingletonFactory to not have to create a new factory every time. The only difference would be that the SingletonFactory’s constructor would take a ‘clazz’ parameter of type Function and return a new instance of the passed class.

That of course isn’t the neatest way to handle the issue. We will now go a step further and use a Context class to bind classes to string identifiers. The Context checks if the class implements the Singleton interface. If that is the case it creates a new SingletonFactory instance assigning the class to it. If you now use the Context.lookup(String) method passing in the identifier, the Factory’s getInstance() operation is being called returning an instance of the assigned class. As you can see this implementation is much more flexible. You do not have to care about whether the class is a Singleton or not. You can also easily substitute the class returned by the Context.lookup(String) method for a given identifier. All you have to care about is that the new class substituting the old one implements the same interface. All this should of course be done declaratively.
A little variation of this approach would be to determine whether to use the SingletonFactory or a normal one not by implementing the Singleton interface but by calling the Context’s bindSingleton() operation or by doing this declaratively. Doing it that way every class could be a potential Singleton without having to change anything inside of it. To achieve all this we need a bunch of new classes and interfaces. These classes or interfaces are:

  • Interface org.swacker.designpattern.Singleton:

    This interface declares no operations. It is just used to distinguish a Singleton from a normal class.
  • Interface org.swacker.naming.Context:

    The Context interface declares the operations to bind, unbind and rebind an object to a specific name.
  • Interface org.swacker.naming.Factory:

    Factory declares the getInstance() operation that should be implemented by all factories.
  • Class org.swacker.naming.ClassContext:

    ClassContext implements the Context interface. Only classes are allowed to be bound to string identifiers. It gets internally checked whether the passed class is a Singleton using the above explained check mechanism.
  • Class org.swacker.naming.SimpleFactory:

    SimpleFactory is a simple implementation of the Factory interface that just returns a new instance of the passed class, not storing old ones.
  • Class org.swacker.naming.SingletonFactory:

    SingletonFactory stores the firstly instantiated instance of a class and returns this instance every time the SingletonFactory.getInstance() operation gets called.
  1. interface org.swacker.designpattern.Singleton {
  2. }
  1. interface org.swacker.naming.Context {
  2.   public function bind(name:String, object):Void;
  3.   public function rebind(name:String, object):Void;
  4.   public function rename(oldName:String, newName:String):Void;
  5.   public function unbind(name:String):Void;
  6.   public function lookup(name:String);
  7. }
  1. interface org.swacker.naming.Factory {
  2.   public function getInstance(Void);
  3. }
  1. import org.as2lib.env.except.Exception;
  2. import org.as2lib.util.ClassUtil;
  3. import org.swacker.naming.Context;
  4. import org.swacker.naming.Factory;
  5. import org.swacker.naming.SimpleFactory;
  6. import org.swacker.naming.SingletonFactory;
  7. import org.swacker.designpattern.Singleton;
  8.  
  9. class org.swacker.naming.ClassContext implements Context {
  10.   private var registry:Object;
  11.    
  12.   public function ClassContext(Void) {
  13.   }
  14.    
  15.   public function bind(name:String, object):Void {
  16.     if (registry[name]) {
  17.       throw new Exception("The name [" + name + "] is already in use.", this, arguments);
  18.     }
  19.     var factory:Factory;
  20.     if (ClassUtil.isImplementationOf(object, Singleton)) {
  21.       factory = new SingletonFactory(object);
  22.     } else {
  23.       factory = new SimpleFactory(object);
  24.     }
  25.     registry[name] = factory;
  26.   }
  27.    
  28.   public function rebind(name:String, object):Void {
  29.     unbind(name);
  30.     bind(name, object);
  31.   }
  32.    
  33.   public function rename(oldName:String, newName:String):Void {
  34.     bind(newName, registry[oldName]);
  35.     unbind(oldName);
  36.   }
  37.    
  38.   public function unbind(name:String):Void {
  39.     if (!registry[name]) {
  40.       throw new Exception("You tried to unbind a name [" + name + "] that has no binding.", this, arguments);
  41.     }
  42.     registry[name] = undefined;
  43.   }
  44.    
  45.   public function lookup(name:String) {
  46.     return Factory(registry[name]).getInstance();
  47.   }
  48. }
  1. import org.swacker.naming.Factory;
  2.  
  3. class org.swacker.naming.SimpleFactory implements Factory {
  4.   private var clazz;
  5.    
  6.   public function SimpleFactory(clazz:Function) {
  7.     this.clazz = clazz;
  8.   }
  9.    
  10.   public function getInstance(Void) {
  11.     return (new clazz());
  12.   }
  13. }
  1. import org.swacker.naming.Factory;
  2.  
  3. class org.swacker.naming.SingletonFactory implements Factory {
  4.   private var instance;
  5.    
  6.   public function SingletonFactory(clazz:Function) {
  7.     instance = new clazz();
  8.   }
  9.    
  10.   public function getInstance(Void) {
  11.     return instance;
  12.   }
  13. }

Not every thought has been implemented yet. Including the declarative stuff. The code shown here is also not fully worked out. It are all basic implementations that are right now only intended for explanation reasons. I am planning to offer support for everything I have written above in one of the next releases of the as2lib. If you have any questions or suggestions leave a comment.

To complete this post I’m now going to show you why not just use static methods and variables to implement Singletons. The problems using this approach:

  • Everything I told you above would not work using static methods and variables.
  • You could not use the constructor to do the core initialization. That means you had to do the core initialization in a static manner. Doing that causes the initialization to be done whether the class is needed or not which would create unnecessary overhead.
  • Another major disadvantage is that you could not take advantage of interfaces and inheritance.
  • You also could not use ‘this’ directly in one of the static methods becuase it would cause a compile time error. You had to outwit it using eval(”th” + “is”).

This should be enough disadvantages to not even think about implementing a Singleton using static methods and variables.

Tuesday, September 23rd, 2003

State

Basic implementation:

// :: Context :: //
class Context{
        private var state:State;

        public function request():Void{
                state.handle();
        }
        public function setState(aState:State):Void{
                state = aState;
        }
        public function getState():State{
                return state;
        }
}

// :: State :: //
interface State{
        public function handle():Void;
}

// :: ConcreteStateA :: //
class ConcreteStateA implements State{
        public function handle():Void{
                trace(”ConcreateStateA: handle“);
        }
}

// :: ConcreteStateB :: //
class ConcreteStateB implements State{
        public function handle():Void{
                trace(”ConcreateStateB: handle“);
        }
}

// usage
aContext = new Context();
aContext.setState(new ConcreteStateA());
aContext.request();
aContext.setState(new ConcreteStateB());
aContext.request();

This is only one way to change the state. I have chosen this way for simplicity. You could also change the state dynamically depending on for example a local connection or a mouse press etc. It depends on the context.

Sunday, September 21st, 2003

Composite

Basic implementation:

// :: Component :: //
interface Component{
        public function operation():Void;
}

// :: Leaf :: //
class Leaf implements Component{
        private var number:Number;

        public function Leaf(aNumber:Number){
                number = aNumber;
        }
        public function operation():Void{
                trace(”Leaf ” + number + “: operation“);
        }
}

// :: Composite :: //
class Composite implements Component{
        private var children:Array;

        public function Composite(){
                children = new Array();
        }
        public function operation():Void{
                for(var i:Number=0; i < children.length; i++){
                        children[i].operation();
                }
        }
        public function addComponent(aComponent:Component):Number{
                return children.push(aComponent)-1;
        }
        public function removeComponent(aNumber:Number):Void{
                children.splice(aNumber, 1);
        }
        public function getChild(aNumber:Number):Component{
                return children[aNumber];
        }
}

// usage
var aComponent:Composite = new Composite();
aComponent.addComponent(new Leaf(0));

var aComposite:Composite = new Composite();
aComposite.addComponent(aComponent);
aComposite.addComponent(new Leaf(1));
var leaf2 = aComposite.addComponent(new Leaf(2));
aComposite.addComponent(new Leaf(3));

aComposite.operation();

trace(”——————————–“);

aComposite.getChild(leaf2).operation();

trace(”——————————–“);

aComposite.removeComponent(leaf2);
aComposite.operation();

/* Output:
Leaf 0: operation
Leaf 1: operation
Leaf 2: operation
Leaf 3: operation
——————————–
Leaf 2: operation
——————————–
Leaf 0: operation
Leaf 1: operation
Leaf 3: operation
*/
Tuesday, September 16th, 2003

Singleton

Dave Yang already showed on his blog how to implement the Singleton Pattern. Therefore I think I don’t have to rewrite the code. Here’s the link: Singleton Pattern by Dave Yang.