Home > Beginner's Guide, Decorator > Well-Armored Warrior:ActionScript 3.0 Decorator for Beginners

Well-Armored Warrior:ActionScript 3.0 Decorator for Beginners

Decorator Adds Changes without Changing the Object

Decorator Adds Changes without Changing the Object

Decorating an Object

In looking over the chapter on the Decorator pattern in our book I’ve felt that maybe I picked too complex a set of examples. In a Decorator example on this blog I attempted to remedy that with a very easy yet somewhat abstract example. However, I’ve decided to try and have a hugely simple example that is both interactive and solves a practical program in games. The knights of yore represent a good metaphor for the Decorator Design Pattern. The Component (knight) is decorated with armor. The same knight may have more than a single suit of armor and yet easily be recognized as the same knight. We could put him in a time machine and trade his steel suit of armor with one decorated with kevlar or some other modern weapon-stopping armor.

In a game context, different characters can be decorated with different weapons, armor and capabilities. If we have to provide our characters with a set of features at the outset, we can get stuck easily if we want to make changes to the character. The Decorator pattern recognizes that in dynamic situations, you need dynamic solutions. You don’t want to have to create a new character every time the character changes. With the Decorator, it’s easy to make changes without changing the core component (character). In this example, I used a graphic warrior and three different graphic semi-opaque graphic armor. To optimize the simplicity, each of the four elements—a component (character) and three types of armor (shield, breast plate and helmet) serve to illustrate the pattern. Further, I used a different class for each as well. These were stored in the library as Sprites. Use the Play and Download buttons below to become familiar with the pattern:
playkilroy

If you click the Play button, the initial figure is the “Concrete Component” participant, and as you click each button in turn, a new “Concrete Decorator” appears. (If you keep clicking the decorator buttons, the decorators accumulate. You can add a line of code to remove them easy enough, but I didn’t in an effort to keep it as simple as pie.)

The Classes

The class diagram and the whole pattern always leaves me with a question mark over my head like a befuddled cartoon character. However, after looking at the class diagram for a while, it begins to make sense. The unusual aspect of the pattern is that the abstract class Decorator subclasses the abstract class Component. In other words, one abstract class inherits from another. Further, the Decorator “wraps” the Component. Figure 1 shows the Decorator class diagram:

<em><strong>Figure 1:</strong> Decorator class diagram</em>

Figure 1: Decorator class diagram

The major feature of the design pattern is the curving reference (an aggregate relationship) from the Decorator to the Component. The inheritance of the ConcreteComponent is a straight inheritance from an abstract class. That’s pretty clear. However, the “wrapping” looks a bit different and one way to “see” it is through the Client. Assuming that the concrete object (the Warrior) is already there, the following code is involved in wrapping the component in a concrete decorator (a Shield, for example.) The code in the Client looks like the following:

?View Code ACTIONSCRIPT
1
2
conComponent = new DecShield(conComponent);
mover.addChild(conComponent.getarmor());

In this example you have the following:

  • conComponent is typed as a Component
  • conComponent instantiates a concrete decorator with itself as a parameter
  • the conComponent instance invokes the getarmor() method, a Component method, that returns the armor’s image

The trick is that each of the concrete decorators inherits both the Component and Decorator interfaces. As a result, the armor (or anything else) is able to change the appearance of the component without changing the concrete component itself.

A Running Start

In looking at the code, I think that it may be helpful to begin with the Client that makes a request through the Component abstract class. It’s a little busy for a Client because it sets up a UI and allows users to add one concrete decorator at a time. Yet in all, it’s pretty simple:

?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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package
{
	import flash.display.Sprite;
	import fl.controls.Button;
	import flash.events.MouseEvent;
 
	public class Client extends Sprite
	{
		private var conComponent:Component=new Warrior();
		private var btnShield:Button=new Button();
		private var btnBodyArmor:Button=new Button();
		private var btnHelmet:Button=new Button();
		private var mover:Sprite=new Sprite();
		public function Client()
		{
			btnShield.addEventListener(MouseEvent.CLICK,addShield);
			btnShield.x = 10,btnShield.y = 40,btnShield.label = "Shield";
			addChild(btnShield);
 
			btnBodyArmor.addEventListener(MouseEvent.CLICK,addBodyArmor);
			btnBodyArmor.x = 10,btnBodyArmor.y = 65,btnBodyArmor.label = "Body Armor";
			addChild(btnBodyArmor);
 
			btnHelmet.addEventListener(MouseEvent.CLICK,addHelmet);
			btnHelmet.x = 10,btnHelmet.y = 90,btnHelmet.label = "Helmet";
			addChild(btnHelmet);
 
			mover.addChild(conComponent.getarmor());
			mover.x = 100,mover.y = 100;
			addChild(mover);
		}
 
		private function addShield(e:MouseEvent):void
		{
			conComponent = new DecShield(conComponent);
			mover.addChild(conComponent.getarmor());
		}
 
		private function addBodyArmor(e:MouseEvent):void
		{
			conComponent = new DecBodyArmor(conComponent);
			mover.addChild(conComponent.getarmor());
		}
 
		private function addHelmet(e:MouseEvent):void
		{
			conComponent = new DecHelmet(conComponent);
			mover.addChild(conComponent.getarmor());
		}
	}
}

Automatically places the Warrior (concrete component) on the screen and lets the user add decorators one at a time. In studying the unusual way in which requests are made for each decorator, we will now back up into the abstract Component and Decorator classes.

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//Component
package
{
	import flash.display.Sprite;
	import flash.errors.IllegalOperationError;
 
	//Abstract class. Do not instantiate directly
	//Extend the class for concrete child classes
 
	public class Component
	{
		protected var armor:Sprite;
 
		public function getarmor():Sprite
		{
			return armor;
		}
	}
}

In this particular case, the abstract class isn’t very abstract. The single method sets up the component interface, as either a concrete component or a concrete decorator to be sent back as a Sprite instance. The details of the getarmor() method are specified in the concrete decorators.

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
package
{
	import flash.errors.IllegalOperationError;
 
	//Abstract class. Do not instantiate directly
	//Extend the class for concrete child classes
 
	public class Decorator extends Component
	{
		protected var char:Component;
	}
}

The Decorator, which extends the Component, is made up of a single property that is typed as a Component. However, the property is used as a reference to the object decorated and not a change in the concrete component itself.

The Concrete Classes

The concrete classes are ones that provide an image on the screen. All of them were created in the Flash Pro library, but they could have been done by creating sprites classes with Flash Builder. (In a mini-post later on this week, there’ll be an example of how to use Flash Builder to create graphic Sprites equivalent to those done in Flash Pro.)

The concrete component has only a single component that will be decorated with the concrete decorators. In this case, the concrete component class is named “Warrior.” It provides a warrior to dress with armor.

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
//Concrete Component
package
{
	//Concrete component
	public class Warrior extends Component
	{
		//Delphi is a Sprite class
		public function Warrior()
		{
			armor=new Delphi();
		}
	}
}

The Warrior uses an instance of the Delphi class that is nothing more than a graphic depiction of the warrior to be decorated. (By the way, “Delphi” is a conjunction of the Greek letters Delta Phi or DP or Design Patterns!)

The concrete decorators are all tied into the concrete component through the wrapping of the component. Each of the concrete decorators extends the Decorator. However, since the Decorator extends the Component, each of the concrete component also inherit the Components methods and properties. Because the Component class is abstract (in the way it is treated), each method must be overridden. In this way, unique elements can make up the different concrete decorations. However, to keep everything as simple as possible, the Sprite classes are just ones in the Library.

?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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//Shield
package
{
	import flash.display.Sprite;
	//Concrete decorator Shield
 
	public class DecShield extends Decorator
	{
		public function DecShield(char:Component)
		{
			this.char=char;
		}
		//Shield is a Sprite class
		public override function getarmor():Sprite
		{
			armor=new Shield();
			armor.x=100,armor.y=100;
			return armor;
		}
	}
}
//Body Armor
package
{
	import flash.display.Sprite;
	//Concrete decorator Body Armor
 
	public class DecBodyArmor extends Decorator
	{
		public function DecBodyArmor(char:Component)
		{
			this.char=char;
		}
		//BodyArmor is a Sprite class
		public override function getarmor():Sprite
		{
			armor=new BodyArmor();
			armor.x=12,armor.y=57;
			return armor;
		}
	}
}
 
//Helmet
package
{
	import flash.display.Sprite;
	//Concrete decorator Helmet
 
	public class DecHelmet extends Decorator
	{
		public function DecHelmet(char:Component)
		{
			this.char=char;
		}
		//Helmet is a Sprite class
		public override function getarmor():Sprite
		{
			armor=new Helmet();
			armor.x=39,armor.y=-9;
			return armor;
		}
	}
}

Adding Armor

Let me make a couple of suggestions. First, add a weapon or two or more armor. This will entail creating a new concrete decorator. You can make the armor or weapon as simple or complex as you like. If you’re using Flash Builder, just create a Sprite class with graphics that depict a weapon. (By the way, later this week, I want to do a short post on creating your own image class library if you’re using Flash Builder. (This is just for beginners; so it will be simple.) Anyway, if you play with it, you’ll come away understanding it far more than just looking at what I’ve done. Besides it’s fun and we’d really like to see some of your ideas.

Share

Related posts:

  1. ActionScript 3.0 Easy and Practical Decorator Design Pattern
  2. Beginners OOP & Design Patterns in ActionScript 3.0 Post 1 : Rolls-Royces in the Junk Yard
  3. Beginners OOP & Design Patterns in ActionScript 3.0 Post 2: Code Organizer
  1. Martin
    June 15, 2011 at 4:23 am | #1

    Thanks. But the latest decorator is the only visible one, we can´t get the previous ones. We got the sprites, but the information gets lost. But if we get into a fight, we might need them.

    • June 15, 2011 at 7:17 am | #2

      Hi Martin,

      I’m working on a new mini-post right now. For those using Flash Builder, it can be tricky to get the Sprite classes with the graphics. So, I’ve created AS3 classes for the 3 types of armor.

      You can then use that information to code up the Warrior!!

      Kindest regards,
      Bill

  2. Jan
    June 15, 2011 at 7:05 am | #3

    Hi Bill,
    great post as always and interesting pattern.
    What i don´t quite get is, what´s the concrete decorator doing with the component, handed to him in the constructor?
    Is it so you can go down the hierarchy and get the previous armor elements?

    To get a warrior with full armor, you have to decorate it three times, call the getarmor()-Method three times and add the results to the display list.
    Or is there a way to get the full set from the current decorated object with one call?

    Like:

    conComponent = new DecShield(conComponent);
    conComponent = new DecBodyArmor(conComponent);
    conComponent = new DecHelmet(conComponent);
    mover.addChild(conComponent.getCurrentArmor());

    Especially for later use, when we get handed a warrior object and want to display it with the armor configured by the player.

    Cheers Jan

    • June 15, 2011 at 7:21 am | #4

      Hi Jan,

      You’re exactly right! I just put in the buttons to help you visualize each of the decorator armor pieces go on.

      Now I’m finishing up a mini-post for FB users to create a Sprite class for either the original armor or for adding new ones on their own. You can code your own Warrior since I left that up to someone with a modicum of graphics ability!

      Kindest regards,
      Bill

  3. Martin
    June 15, 2011 at 1:36 pm | #5

    Hi Bill,

    I´m not sure but I think, we talked at cross-purposes (I need to improve my english).

    I can remember an decorator example, where all decorator infos were stored in one string (I thing it´s in your book, not sure).

    What I miss in your example is the changing state of the warrior in a non-visible way. If he has a shield, his defense would may increase by 5 (whatever) and so on. But how can I know that he has a shield?

    Sorry, I think this out of your goal, and I think it is out of the goal of the decorator pattern. It´s not his target to change states, like “hasShield = true”. A decorator may brings sth. to the component, the component never knew about.

    • June 15, 2011 at 2:32 pm | #6

      Hi Martin,

      This example is using graphic Sprite classes to illustrate the decoration process. That’s all. However, because the decorations are classes themselves, you can add any property or method you want. Likewise, the component could have properties that indicate whether or not it has a different decoration. For example the Warrior class could have Boolean variables that default to false:

      ?View Code ACTIONSCRIPT
      1
      2
      3
      
      var hasShield:Boolean=false;
      var hasBodyArmor:Boolean=false;
      var hasHelmet:Boolean=false;

      When a decorator is added, it would change that decorator indicator to true. For example, when a Shield object is added, the variable hasShield would be changed to true.

      Remember, that the concrete decorator object inherits both the Component and Decorator; so properties of the Component are inherited by both the concrete component and the concrete decorator.

      See if you can tweak it to maintain the Decorator pattern and provide properties that indicate their state (true/false).

      Kindest regards,
      Bill

      • Julien
        June 30, 2011 at 1:57 am | #7

        Hi,

        Would not be better to use component wrapped and let decorator to add it properties, instead a boolean in warrior.

        For example a warrior could have a method get defense():int
        which is by default “5″, and the shield1 decorator override and complete it in the manner


        public function get defense():int{
        return char.defensse + "20";

        It’s even a question than an affirmation.

        Cheers Julien

        • June 30, 2011 at 8:35 am | #8

          Hi Julien,

          What class is the get defense() function in? Is it part of the component or decorator classes?

          I’m not sure what you mean by

          “It’s even a question than an affirmation.”

          Could you expand it out to an example inside one of the Decorator’s Participants? It looks like an interesting idea, but I’d like to see it in context to provide a good response.

          Kindest regards,
          Bill

          • Julien
            July 1, 2011 at 2:16 am | #9

            Hi Bill,

            Sorry for my english, i wrote as i thought in french so i could be not clear.

            I thought defense propertie as a part of the component that should be updated by the current decorator as it wraps the component.

            In that manner, i thought using an sword could add 5 point to warrior defense, and next if warrior + sword is wrap by a shield which add 20 pts of defense, the warrior’s total defense shoulb be warrior defense + 5 + 20.

            It is what i understand of the Decorator Pattern but i’m not sure of my understanding.

            In the same idea, why Decorator classes extends Component and not just implements an interface IComponent which would force Decorator to use the component it wraps.
            For example if warrior component has a method
            get strength():int, ShieldDecorator does not affect strength so its implementations only return component.strength.

            Do I have correct ? In the Pattern scheme, Decorator Implements Component Interface so why does it have to extends Component in the same time ?

            Thanks in advance to your patience.
            Julien

  4. July 1, 2011 at 5:32 am | #10

    Bonjour Julien,

    Your English is far superior to my French; so you owe me no apology.

    Your question is an excellent one, but the answer is not easy. The Decorator is the only pattern where an abstract class (Decorator) subclasses another abstract class (Component). The concrete component is then wrapped by the Decorator, which in turn wraps the Concrete Component(s). In this way, the concrete component “belongs” to both the Component and the Decorator, but the concrete component does not have to be changed. This is another example of loose coupling and easy update.

    Does that help?

    Amicalement,
    Bill

  5. Olivier
    November 14, 2011 at 2:00 am | #11

    Hi From France
    First I bought your incredible book as3 Design Pattern and i have to thank you two( writters ) for putting the light on Design Pattern for us “poor as1 migrants”.

    I apologize in advance for my poor english

    Oops the message has been sent while i was pressing enter on my keyboard ( may be the state pattern hasn’t been implemented :) )
    messageState:writing vs messageState writingComplete.

    However i had a big question :
    is there any difference between Abstract Class and Interface ?
    this is very confusing for me. I prefer interface because a class can implement more than one Interface and then give some multi inheritence like.

    Sure i know the keyword Abstract doesn’t exist in as3. But in some cases in the book you use it. In the simple factory method in the book you use an Abstract class. Had it been the same with an interface ?

    to conclude : “joli coup” for your book
    Best regards Olivier

    • November 14, 2011 at 2:47 am | #12

      Bonjour Olivier,

      The difference between an interface and an abstract class is that some parts of an abstract class may be concrete, and you can have both abstract properties and methods. Interfaces only include abstract methods. It may be helpful to think of them both as “interfaces” and use them for implementing concrete classes. In fact, wherever you have inheritance, you should use either type of interface.

      We’re all ‘Poor AS1 Migrants’ at one time! We’re glad you liked our book.

      Amicalement,
      Bill

  1. June 17, 2011 at 8:27 pm | #1
  2. June 24, 2011 at 4:03 am | #2

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>