Bookmark and Share

Decorator pattern provides 2 main features:

1. It attaches additional responsibilities to an object dynamically.
2. It provides a flexible alternative to sub-classing for extending functionality.

Here I am going to use D&D character creation as an example although I feel it is better to use Factory pattern instead but for the sake of this tutorial, let’s just use it.

We have “Character” abstract class and “Human” class extends it:

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package {
 
	// Abstract class
	public class Character {
 
		protected var name:String;
 
		function Character() {}
 
		public function getName():String {
			return name;
		}
 
		public function fight():String {
			throw new Error("Need to extend it!");
		}
 
	}
 
	// Concrete class
	public class Human extends Character {
 
		function Human() {
			name = "Human";
		}
 
		override public function fight():String {
			return name + " fight with hand";
		}
 
	}
 
}

Now we want to attach the character with weapons, we create “WeaponDecorator” abstract class that extends “Character” which ensure the interface compatibility. Then we create “Sword” class that extends it and pass the “Character” reference through the constructor by composition and attach new weapon in “fight()” method:

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package {
 
	// Abstract decorator
	public class WeaponDecorator extends Character {
 
		protected var char:Character;
 
		function WeaponDecorator(char:Character) {
			this.char = char;
		}
 
	}
 
 
	// Concrete decorator
	public class Sword extends WeaponDecorator {
 
		function Sword(char:Character) {
			super(char);
		}
 
		override public function fight():String {
			return (this.char.fight() + " and sword");
		}
 
	}
 
}

Here is the client code:

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package {
 
	import flash.display.*;
	import flash.events.*;
 
	public class Main extends MovieClip {
 
		function Main() {
 
			var human:Character = new Human();
			trace(human.fight());
 
			// Decorating human with sword
			var swordman:WeaponDecorator = new Sword(human);
			trace(swordman.fight());
 
		}
 
	}
 
}
 
// Output:
// Human fight with hand
// Human fight with hand and sword

Of course, you can add another weapon by creating another weapon class like “Axe” and pass the sword reference to it etc…