Truckin’ Through ActionScript 3.0 MVC: Part IV—Making Changes

Truckin' thru MVC

Truckin' thru MVC

I mentioned that updating and changing programs is the sine qua non of Design Patterns. Further, I promised that it wouldn’t take very long to get to Part IV of this series because all I was going to do was to update the original compass program. So that’s what I did, and here is Part IV of Truckin’ Through ActionScript 3.0 MVC.

Adding an Interface for the View

Before adding another view, I wanted to add an interface so that I could use the same Model and Controller classes. The changes are minimal in the revised View classes, and I changed the Client so that it could more easily request any view the user would like. Since you have all of the details about how the MVC works in Parts I-III, I’ll get right into the interface.

In looking at the View class in Part III, you can see that the class has only two methods. By putting them into an interface, we can program to the interface instead of the implementation. That means that as long as the same interface is used, you can use the same Model and Controller without any changes at all. As usual, interfaces are fairly short, and this one is no exception.

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
package 
{
	import flash.display.Sprite;
	import flash.events.Event;
 
	public interface IView
	{
		function createView(vessel:Sprite):Sprite;
		function update(e:Event):void;
	}
}

Before continuing, click the Play button to test both compasses that have their roots in that interface. (compi?)
play
The Model and Controller classes are identical for both compass examples. Read on to see how easy it is to add views.


Because we now have an interface for the View, we need to update the original View class so that it implements the IView interface. The name of the View classes need to be unique; so the name has been changed from View to ViewAnalog. Likewise, the createAnalog() method has been given the more general name, createView() in line with the more general task of the 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
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
package 
{
	import fl.controls.Slider;
	import fl.events.SliderEvent;
	import flash.display.Sprite;
	import flash.events.Event;
 
	public class ViewAnalog implements IView
	{
		private var model:Model;
		private var controller:Controller;
		private var base:Sprite;
		private var compassRose:Sprite;
		private var pointer:Sprite;
		private var slider:Slider;
 
		public function ViewAnalog(model:Model, controller:Controller, vessel:Sprite)
		{
			this.model=model;
			this.controller=controller;
			base=createView(vessel);
		}
 
		public function createView(vessel:Sprite):Sprite
		{
			//add compass rose and needle
			compassRose=new CompassRose();
			compassRose.x=250,compassRose.y=250;
			vessel.addChild(compassRose);
			pointer=new Pointer();
			pointer.x=0,pointer.y=0;
			compassRose.addChild(pointer);
 
			//**add slider
			var slideHolder=new Sprite();
			vessel.addChild(slideHolder);
			slider=new Slider();
			slider.maximum=360;
			slider.width=slider.maximum;
			slideHolder.addChild(slider);
			slider.x=(250) - (slider.width/2);
			slider.y=20;
			slider.addEventListener(SliderEvent.CHANGE, controller.newDirection);
 
			return compassRose;
		}
 
		public function update(e:Event):void
		{
			pointer.rotation=model.getDir();
		}
	}
}

As you can see, it’s almost identical to the original View class. Now for the payoff of loose coupling. Instead of an analog compass, this next one is a retro-digital compass. With a black background and green text, it looks like the old monitors with black screens and green output. Placed next to the analog compass, you can see the same exact data in a wholly different framework. Figure 1 compares the different views with the same data:

<em><strong>Figure 1: </strong>Adding new views is easy with MVC</em>

Figure 1: Adding new views is easy with MVC

The following listings shows the changes that were made. Note that instead of using MovieClip objects for display, this next view uses a Shape for the background and a TextField and TextFormat for the value state in the Model. However, both are placed in the vessel Sprite and work just fine. The same Slider with the same code is reused except instead of changing the rotation, the value is placed in a TextField object.

?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
65
66
67
68
69
package 
{
	import fl.controls.Slider;
	import fl.events.SliderEvent;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.display.Shape;
 
	public class ViewRetro implements IView
	{
		private var model:Model;
		private var controller:Controller;
		private var base:Sprite;
		private var slider:Slider;
		//Instantiate text field and format
		private var txtFld:TextField=new TextField();
		private var format:TextFormat=new TextFormat();
 
		public function ViewRetro(model:Model, controller:Controller, vessel:Sprite)
		{
			this.model=model;
			this.controller=controller;
			base=createView(vessel);
		}
 
		public function createView(vessel:Sprite):Sprite
		{
			//Create backdrop using a Shape
			var crt:Shape=new Shape  ;
			crt.graphics.beginFill(0x000000);
			crt.graphics.lineStyle(0,0x000000);
			crt.graphics.drawRoundRect(100,60,300,50,6);
			crt.graphics.endFill();
			vessel.addChildAt(crt,0);
 
			format.color=0x00ff00;
			format.font="OCR A Std";
			format.size=32;
 
			txtFld.defaultTextFormat=format;
			txtFld.x=220;
			txtFld.y=70;
			//Set default value to 0 so that 
			//it does not display null--NaN
			txtFld.text=0;
			vessel.addChildAt(txtFld,1);
 
			//add slider
			var slideHolder=new Sprite();
			vessel.addChild(slideHolder);
			slider=new Slider();
			slider.maximum=360;
			slider.width=slider.maximum;
			slideHolder.addChild(slider);
			slider.x=(250) - (slider.width/2);
			slider.y=20;
			slider.addEventListener(SliderEvent.CHANGE, controller.newDirection);
 
			return vessel;
		}
 
		public function update(e:Event):void
		{
			txtFld.text=model.getDir();
		}
	}
}

Finally, the Client has to be changed a bit so that selecting one view or another is simple to do. (You can get fancier if you like and set up a UI selection.) The following listing shows the Client.

?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
package 
{
	import flash.display.Sprite;
 
	public class Client extends Sprite
	{
		private var model:Model;
		private var view:IView;
		private var controller:Controller;
 
		public function Client()
		{
			setMVC("r");
		}
 
		private function setMVC(viewType:String):void
		{
			model = new Model();
			controller=new Controller(model);
			switch (viewType)
			{
				case "a" :
					view=new ViewAnalog(model,controller,root);
					break;
				case "r" :
					view=new ViewRetro(model,controller,root);
			}
			model.addEventListener(Model.UPDATE, view.update);
		}
	}
}

As far as I can see, the MVC fulfills exactly what GoF had intended for it to do—illustrate how by loosening up classes, updating and adding new elements is easy. While I’ve been busy with OOPSLA and work, it took me a good deal of time to develop the original MVC. However, when it came to updating the program, I was able to do it quite quickly. If you’d like to download the entire set of files, click the download button that Barbara Parkman send us.
kilroy

Make Your Own View

To really understand how the MVC works, you will find it helpful to create your own View for this program. Just add any kind of view you want, from simple to elaborate, and have it display data from the Model. There’s nothing you can break, and it will demonstrate how useful Design Patterns are when adding new elements to a program. In fact, we can make it into a Golden Lunch Bucket Contest if enough of you are interested. Enjoy!

  • Share/Bookmark

Related posts:

  1. Truckin’ Through ActionScript 3.0 MVC: Part III—An Analog Compass
  2. Truckin’ Through ActionScript 3.0 MVC: Part II—Reality Sui Generis or Collection of Spare Parts?
  3. Is MVC Obsolete? Flex, ActionScript 3.0 and the MVC Design Pattern

0 Response to “Truckin’ Through ActionScript 3.0 MVC: Part IV—Making Changes”


  • No Comments

Leave a Reply