ActionScript 3.0 Saturated Bridge Design Pattern 3: Reuse and Change

Update Bridge and Participants
When we think of update and change, typically we think of adding new implementations to existing structures. However, what about tweaking a pattern? If you want to reuse a general pattern (like the Bridge we’ve been discussing), what are the “rules” about changing the pattern?
Generally, the purpose of using design patterns is so that you can make changes without disrupting the current objects. That is, you can add a new object in the form of an implemented interface or abstract class without having to worry about existing objects being disrupted or crashing the system. The bigger the project, the more important this is.
How about making a new pattern based on a few adjustments to one of the pattern participants? If you want to re-use the pattern with just a few changes, and you don’t care about the current participants, you can make small changes with big results.
The Movie Clip and Cuckoo Clock
After implementing the alarm clocks, made up of a bridge aggregated instance consisting of an AlarmClock abstract class and an Alarm interface, I considered adding a cuckoo clock to the mix. Instead of just adding a sound, I wanted to have an animated bird pop out of a door making a cuckoo sound and a swinging pendulum along . Figure 1 shows what I wanted to do with my bridge pattern.(Click the Play button to see the results. If you find it easier to follow along with the code in hand, the download button now provides both Flash and Flex compatible files.)

Figure 1: Could a Cuckoo Clock be implemented in a Bridge Design Pattern?
What’s Changed?
The cuckoo clock would have to have some kind of mechanism to have an opening door and a bird pop out. Further, when the cuckoo bird jumps out, he’ll need a “cuckoo” sound coordinated with the opening door. To make life easy, I decided to throw a cuckoo sound, bird and sliding doors into a MovieClip object and stack it on top of the clock. I re-used the BellClock implementation’s of IAlarmClock for the hands on an analog clock. However, I needed to address the MovieClip through the IAlarm implementation. To do that, I had to include a MovieClip parameter in the existing Bridge design. So, I changed the IAlarm interface to the following:
1 2 3 4 5 6 7 8 9 10 | package { import flash.display.MovieClip; public interface IAlarm { function alarmPlay(mc:MovieClip); function alarmOff(mc:MovieClip); } } |
Then in the implementation, I can use the MovieClip with the opening door, cuckoo bird and sound. The implementation looks different from the alarm clock bridge because it does not load an MP3 and it does trigger a play or stop play method in the MovieClip. However, there is no code on the Timeline! It’s all in the implementation of the IAlarm:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package { import flash.display.MovieClip; public class CuckooAlarm implements IAlarm { private var goCuckoo:MovieClip; public function alarmPlay(mc:MovieClip) { goCuckoo=mc; goCuckoo.play(); } public function alarmOff(mc:MovieClip) { goCuckoo=mc; goCuckoo.gotoAndStop(1); } } } |
As you can see, the Bridge pattern is altered very little. The IAlarmClock is the same but the implementation is able to reference the MovieClip through the IAlarm now. The following shows the cuckoo clock’s implementation of IAlarmClock:
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 | package { import flash.display.Sprite; import flash.display.MovieClip; public class CuckooClock extends IAlarmClock { private var minHand:Sprite=new CuckooMin(); private var hrHand:Sprite=new CuckooHr(); private var cFace:MovieClip=new CuckooHouse(); private var alarmDoor:MovieClip=new CuckooDoors(); private var clockUp:Sprite=new Sprite(); public override function curTime():Sprite { alarm=new CuckooAlarm(); cFace.x=100; hrHand.x=208.5,hrHand.y=172; hrHand.rotation=(timeNow.hours+(timeNow.minutes/60))*30; minHand.x=208.5,minHand.y=172; minHand.rotation=timeNow.minutes*6; alarmDoor.x=100,alarmDoor.y=1; alarmDoor.stop(); clockUp.addChild(cFace); clockUp.addChild(alarmDoor); clockUp.addChild(hrHand); clockUp.addChild(minHand); return clockUp; } public override function doAlarm():void { alarm.alarmPlay(alarmDoor); } public override function offAlarm():void { alarm.alarmOff(alarmDoor); } } } |
The clock is constructed very much like the analog clock in the original Bridge example. The only big difference is the addition of the MovieClip instance (alarmDoor). In communicating with the IAlarm (agregatee) the Bridge serves as a … well bridge… for the implemented IAlarmclock (CuckooClock) to pass the message that it wants the cuckoo to chirp or shut up.
Same Old Client
With the simple changes made, the client doesn’t realize or have to realize that anything is really changed. It makes the same kinds of requests as the original clock-building Bridge does.
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 flash.display.Sprite; import fl.controls.Button; import flash.events.MouseEvent; public class ClientCuckoo extends Sprite { private var aClock:IAlarmClock; private var selectCuckoo:Button=new Button(); private var playCuckoo:Button=new Button(); private var quietCuckoo:Button=new Button(); private var clockNow:Sprite=new Sprite(); public function ClientCuckoo() { addChild(clockNow); selectCuckoo.label="Cuckoo Clock"; selectCuckoo.x=10,selectCuckoo.y=310; selectCuckoo.addEventListener(MouseEvent.CLICK,getCuckoo); addChild(selectCuckoo); playCuckoo.label="Play Cuckoo"; playCuckoo.x=10,playCuckoo.y=340; playCuckoo.addEventListener(MouseEvent.CLICK,releaseCuckoo); addChild(playCuckoo); quietCuckoo.label="Quiet Cuckoo!"; quietCuckoo.x=10,quietCuckoo.y=370; quietCuckoo.addEventListener(MouseEvent.CLICK,cageCuckoo); addChild(quietCuckoo); } private function getClock() { removeChild(clockNow); clockNow=aClock.curTime(); clockNow.x=20,clockNow.y=10; addChild(clockNow); } private function getCuckoo(e:MouseEvent) { if (aClock) { aClock.offAlarm(); } aClock=new CuckooClock(); getClock(); } private function releaseCuckoo(e:MouseEvent) { if (aClock) { aClock.doAlarm(); } } private function cageCuckoo(e:MouseEvent) { if (aClock) { aClock.offAlarm(); } } } } |
Despite the fact that I changed the method names in the client, any programmer can see that they’re the same ones used for the original alarm clock. (The changes were to bring attention to the new type of clock.)
Easy Changes
Usually when we think of changes and re-use with design patterns, the focus is on different implementations of existing abstract participants. However, design patterns can be envisioned in terms of small changes in the pattern to produce a new implementation of a pattern with minimal changes but opening up the door for a whole new kind of structure and opportunities for that structure. The Bridge pattern offers the flexibility that all design patterns have in terms of making changes without disruptions in the project. At the same time, new structures are just as easy to change for a new set of possible implementations.
The variation in the Bridge pattern is the implementation of an object. With the two alarm clocks we saw that both different implementations of the clock (analog and digital) and the alarms (bell and music).
This wraps up the saturated Bridge series, and I hope you have enough depts in the design of the pattern to use it when you need an appropriate Behavioral design. In this last installment, the purpose has been to keep in mind that changes are easy when your code is in a design pattern, but you can also make little changes in a pattern to open up a whole new set of possibilities. Remember, all kinds of changes are easy with ActionScript 3.0 using design patterns.








Bill Sanders
Recent Comments