Sometimes ago I have interview with Wooga and although that I expected that they have 1.000.000 Euros annual income as the guy who interview me advertizes, I didn't expect so low level attitude, everything in order to underestimate me as human and developer. Even he is Genius or whatever, he isn't allowed to enforce such attitude of little people as you and me.....
One of the interview questions were about familiarity with Decorator pattern(auf Deutsch Dekuaaatoooohhrhhrhr). Let not get me wrong I myself have basic knowledge of German languages but I've also learned in my home and school education about decency, which doctor House The Interviewer has missed to acquire as foundation of all his ingenuity.
But...let's continue...
Theory(source: WIKI)
"The decorator pattern can be used to extend (decorate) the functionality of a certain object at runtime, independently of other instances of the same class, provided some groundwork is done at design time. This is achieved by designing a new decorator class that wraps the original class. This wrapping could be achieved by the following sequence of steps:
- Subclass the original "Decorator" class into a "Component" class (see UML diagram);
- In the Decorator class, add a Component pointer as a field;
- Pass a Component to the Decorator constructor to initialize the Component pointer;
- In the Decorator class, redirect all "Component" methods to the "Component" pointer; and
- In the ConcreteDecorator class, override any Component method(s) whose behavior needs to be modified.
This pattern is designed so that multiple decorators can be stacked on top of each other, each time adding a new functionality to the overridden method(s).
The decorator pattern is an alternative to subclassing. Subclassing adds behavior at compile time, and the change affects all instances of the original class; decorating can provide new behavior at run-time for individual objects.
."
This especially useful with OO languages that cannot create classes at runtime a.k.a Reflection, in which group Action Script belongs.
There are lot of theory out there, people have written tons of theory examples of coffe and icecream, but let use pattern in real life scenario and compiling to flash display list logic.
"decorating can provide new behavior at run-time for individual objects."
For example you have hero in your game that starts with basic armor( HideHelmet,SteelShield,HideBody)
so hero's armor is decorated like this:
hero.armor= new HideHelmet(new SteelShield(new HideBody(new Cloath));But what if hero found SteelBody which is better then HideBody (you decorated you armor with better defense) or you have magically enhanced HideHelmet (decorated your helmet with enhancement new behavior to give to hero magical resistance for example) , Decorator patter comes as good solution
hero.armor.removeArmorPart(Armor.ARMOR_HELMET); hero.armor.removeArmorPart(Armor.ARMOR_BODY); hero.armor= new ArmorMagicEnhancment(new HideHelmet(hero.armor),new Resistance(10,15)); hero.armor = new SteelBody(hero.armor);
"The decorator pattern can be used to extend (decorate) the functionality of a certain object at runtime,..."
Which component we are planning to decorate at runtime decorating here? The Armor !
package com.example{ import flash.display.DisplayObject; import flash.display.DisplayObjectContainer; import flash.display.Sprite; public class Armor extends Sprite implements IArmor { public static const ARMOR_SHIELD:int=1; public static const ARMOR_BODY:int=2; public static const ARMOR_HELMET:int=4; private var _hasShield:Boolean=false; private var _hasHelmet:Boolean=false; private var _hasBody:Boolean=false; public function get hasBody():Boolean { return _hasBody; } ...
We are creating Armor Decorator class in order to decorate armor. Component got wrapped around decorator class adding new functionality.
package com.example{ import flash.display.DisplayObjectContainer; ///!!! Don't extend ArmorDecorator from Armor (you would use decoupling of decorator from component decorating) Abstract class not available in AS3 public class ArmorDecorator extends Sprite implements IArmor { private var _armorToBeDecorated : IArmor ; private var _type : int ; public function ArmorDecorator( decoratedArmor : IArmor ){
//"In the Decorator class, add a Component pointer as a field;" - we have pointer to armor(_armorToBeDecorated)
_armorToBeDecorated = decoratedArmor; //add decoratedArmor to display list _armorToBeDecorated.getParent().addChild(this); }"In the Decorator class, redirect all "Component" methods to the "Component" pointer "
override public function getDefence ( ) : Number { return _armorToBeDecorated.getDefence() ; } public class ArmorMagicEnhancment extends ArmorDecorator { private var _resistance:Resistance; private var _type:int; private var _armorToBeDecorated:IArmor; public function ArmorMagicEnhancment( decoratedShild : IArmor,resistance:Resistance ){ super (decoratedShild) ; _armorToBeDecorated=decoratedShild;
//Adding "state" = if armor is magical enhanced => add glow
Sprite(_armorToBeDecorated).filters=[new GlowFilter(0xFF00FF)]; _resistance=resistance; } override public function removeArmor(type:int=0):IArmor { //if type!=0 if(type) { //if this type should be removed if(getType()==type) { this.parent.removeChild(this); return _armorToBeDecorated.removeArmor(type); } _armorToBeDecorated=_armorToBeDecorated.removeArmor(type); return this; } else { this.parent.removeChild(this); return _armorToBeDecorated.removeArmor(); } }
In another decorator on top of basic decorator we can add additional decorations(extend and add new operations, behavior and states)
package com.example{ import flash.display.DisplayObjectContainer; import flashx.textLayout.elements.OverflowPolicy; public class HideHelmet extends Helmet { public function HideHelmet( decoratedArmor : IArmor ){ name = "HideHelmet"; super (decoratedArmor) ; } //we are adding some different behavior override public function getDefence ( ) : Number { return super.getDefence() + Settings.HIDE_HELMET_DEFENCE ; } } }
Hero is entity whose armor we are decorating during run-time.
package com.example{ import flash.display.Sprite; public class Hero extends Sprite { private var _armor : IArmor ; public function Hero( ){ } public function get hasBody():Boolean { if(!_armor) return false; return Armor(_armor.getParent()).hasBody; }...to be Continue(part 2 )
Download source
No comments:
Post a Comment