ActionScript 3.0 Protection Proxy Design Pattern 1: Shielding the Real Subject

Proxy and Real Subject
The Easiest Proxy
Of all of the Proxy designs, the Protection Proxy is very simple both in terms of implementation and concept. The Client makes a request to the Proxy, and the Proxy decides whether to give the Client access to the Subject. Where more than a single Subject is available, the Proxy decides on the level of access. For example, we started off with an example of a dating site. Some users have no access to the dating site until they sign up as a customer. Basically, the Proxy denies them all access to the subject. Once they sign up, they may be given access only to a specific gender. For example, the girls may only be given access to boys if that’s who they’re interested in meeting. The Proxy controls that access. Also, they may be given access only to change their own profile; again controlled by the Proxy. Of course the site administrator needs total access so that he can make sure that no one is posting materials that they shouldn’t be. (When I posted that I was an Astronaut, Rock Star who owns a Silicon Valley software company, the administrator changed it—and without my permission!.)
This design requires only three participants to implement : Subject (interface), Proxy and RealSubject with the Client making a request through the Subject interface to the Proxy. Figure 1 shows the Proxy class diagram shows and the different relationships:

Figure 1: Proxy class diagram
The sequence is unique in that the request, while for the RealSubject, goes through the Proxy as shown in the object diagram in Figure 2:

Figure 2: Proxy object diagram
As you can see, the Proxy design is pretty straightforward, and given the three modes (remote, virtual, and protection), it’s versatile. However, in looking at it, it doesn’t seem to do too much in terms of loosening up code and reusability. According to the GoF,
The Proxy pattern introduces a level of indirection when accessing an object. The additional indirection has many uses, depending on the kind of proxy: p. 210
So the key to understanding the Proxy pattern is indirection. We need to consider indirection a bit more, which we begin on the next section.
GoF list three uses of indirection:
- A remote proxy can hide the fact that an object resides in a different address space.
- A virtual proxy can perform optimizations such as creating an object on demand.
- Both protection proxies and smart references allow additional housekeeping when the object is accessed.
Since we’re looking at the Protection proxy, we need to consider what additional housekeeping may entail.
Begin with the premise that a key function of the Proxy pattern is to prevent unnecessary creation of an object—especially a large, expensive one. Imagine a Web site that does not use a proxy but first creates an object with every request and then decides whether or not the request is valid. Thousands of requests along with the creation of the object could possibly slow operations to a crawl and none of the requests would result in using the object. With a Proxy, none of the blocked requests would create an object in the first place because the Proxy would handle the request.
Once the Proxy decides that the request will be allowed, it can handle any number of other chores. We discussed different access rights above when considering a dating site. Why should the requested object have to deal with access rights when the Proxy could do it instead? No reason at all. For this first post on the Protection Proxy, we will only look at handling a single chore—access. However, we should consider how the design pattern might be important for dealing with options.
Loose Coupling and RealSubject Options
One way to look at the Protection Proxy as a way to maintain loose coupling is to consider the flexibility one has in using, changing and adding RealSubject participants. If the Proxy and RealSubject share an interface the same set of parameters and methods can be used for both. Further, having more than one RealSubject is possible because the additional housekeeping is handled by the Proxy. Instead of having a single RealSubject responsible for different levels of access, the Proxy can determine the level of access and call the appropriate RealSubject for any level of access. As a result, the RealSubjects can be only large enough to handle what the access level requires. For example, if one is designing an application where access is to a database object, the object may have the following options:
- Access to data only
- Access to data and adding data
- Access to data, adding data and changing data
- Access to data, adding data, changing data and deleting records
Rather than have the program create a single large complex object for every access, a more efficient design would be to create different RealSubjects depending on level of access. So if most users only have access to read data, the program does not have to create a large complex object that reads, adds, changes and deletes data. At the same time the design can handle all the other levels of access by calling the appropriate RealSubject; it just doesn’t have to invoke them where they’re not required.
So in terms of design patterns, I believe that the Proxy should be considered beyond the basic indirection it provides. As long as the Proxy is handling the access details, the developer does not have to worry about access coding when developing the RealSubjects. Further, he can add, change and remove RealSubjects as needed without disturbing the entire program.
Accessing Text Data using a Name/Value Pair
To start with a simple example, this Protection Proxy monitors requests to open and read a text file. The text file represents any external data, and virtually the same code can be used to read a database. So, treat it as a generic database instead of a text file, and in Part 2, we’ll use a real MySQL database that is called via a PHP program. However, to kick things off, you don’t need a database or PHP—all you need is ActionScript 3.0 and a text file.
The name/value pair is a common data representation. As used with ActionScript 3.0 and external data, each name/value pair is separated by an ampersand (&) in the loaded data stream. For example, suppose we we want to have three variables representing name, city and country, the data stream would be organized as follows:
name=Nelson Mandela&city=Johannesburg&country=South Africa
The variables are accessed as properties of the loaded object. In this case the object is a URLVariable, and to access it use the following code where NCC is the URLVariable instance:
display.txt=NCC.name;
display.txt +=NCC.city;
display.txt +=NCC.country;
In order to better simulate a database table, the variables (name) will be given the name record followed by a number. Open a text editor (Notepad or TextEdit will work fine) and enter the following:
1 2 3 4 5 6 7 8 | record1=001 Fred Smith programmer ActionScript 3.0 &record2=002 Hanna Brauer programmer JavaScript &record3=003 Aalok Gupta designer Adobe Illustrator &record4=004 Anna Petrov designer Adobe Photoshop &record5=005 Iracema Galleti programmer ActionScript 3.0 &record6=006 Roberto Gonzalez programmer PHP &record7=007 Abeeku Badu programmer Java &record8=008 Fang Yin Zhao designer Adobe Illustrator |
Save the text file as fromText.txt. Place the file in the same directory as the other ActionScript 3.0 files you will create for the Protection Proxy.
The Subject and its Children
The Subject participant is some kind of interface—either an interface or abstract class. For this project, I used an interface named ISubject. It has a single abstract method, pxRequest(). (Were request not a built-in method in ActionScript 3.0, I would have used that name.)
1 2 3 4 5 6 7 8 | package { import fl.controls.TextArea; interface ISubject { function pxRequest(tx:TextArea,un:String,pw:String):void; } } |
As far as interfaces go, ISubject is a bit more busy than most. It only has a single method, but that method has three parameters and the interface had to import a TextArea control. The reference to the TextArea is to “carry back” the reference to the Client request. However, because I was unable to find a way to return the contents of the text file, I carried the output control all the way to the RealSubject. The user name and password made up the two string parameters.
The Proxy Class
I named the Proxy class SubProxy (for Subject Proxy) because Proxy is a reserved word (for an ActionScript 3.0 class.) In this implementation, the SubProxy class simply checks to see if the username and password or acceptable, and if so, it calls the RealSubject. Otherwise it dismisses the request.
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 { import fl.controls.TextArea; public class SubProxy implements ISubject { private var realSub:ISubject; private var txtArea:TextArea; private var un:String; private var pw:String; public function pxRequest(tx:TextArea,un:String,pw:String):void { this.un=un; this.pw=pw; txtArea=tx; if (this.un=="Bill" && this.pw=="as3") { realSub=new RealSubject(); realSub.pxRequest(txtArea,null,null); } else { txtArea.text="Adios..."; } } } } |
An important feature to note is in the SubProxy class is the RealSubject request (realSub.pxRequest(txtArea,null,null);). The second two parameters requesting strings for a username and password are set to null. The null primary expression keyword is not a typed object and works well for filling empty parameters were required by the interface. In this case I wanted to bring it to your attention to emphasize that all housekeeping chores are handled by the SubProxy class. In Part II, you will see far more work by the Proxy, but the RealSubject only does what it’s requested to do—which does not include housekeeping.
The RealSubject Class
Think of the RealSubject participant in the Protection Proxy design pattern as any useful object. In this case, the useful object is one that returns data from a text file. It does so by taking the data from the text file and putting it into a TextArea object.
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.net.URLRequest; import flash.net.URLVariables; import flash.net.URLLoader; import flash.net.URLRequestMethod; import flash.events.Event; import fl.controls.TextArea; public class RealSubject implements ISubject { private var urlString:String="fromText.txt"; private var dataNow:URLVariables; private var txtLoader:URLLoader = new URLLoader(); private var requestNow:URLRequest=new URLRequest(urlString); private var tx:TextArea; public function pxRequest(tx:TextArea,un:String,pw:String):void { this.tx=tx; requestNow.method=URLRequestMethod.POST; txtLoader.addEventListener( Event.COMPLETE, loadTXT ); try { txtLoader.load( requestNow ); } catch (e:ArgumentError) { this.tx.text=e; } catch (e:SecurityError) { this.tx.text=e; } } private function loadTXT( e:Event ):void { txtLoader.removeEventListener( Event.COMPLETE, loadTXT ); dataNow=new URLVariables(txtLoader.data); tx.text=dataNow.record1; tx.appendText(dataNow.record2); tx.appendText(dataNow.record3); tx.appendText(dataNow.record4); tx.appendText(dataNow.record5); tx.appendText(dataNow.record6); tx.appendText(dataNow.record7); tx.appendText(dataNow.record8); } } } |
The difficulty I had with this program was trying to return the data. The original request relies on an event (COMPLETE) to set the stage for using the data. Prior to that event, nothing can be returned, and the event handler cannot be called directly. Using a trace statement works fine, but beyond debugging it’s useless. I could find no way to use the TextArea component beyond the Client without passing it along as a parameter. (Apparently, no one else could either from searching the Web. However, if you have a way to return data from the RealSubject using a return statement—please send it in with working code.) Anyway, as you have seen, this technique works perfectly well.
The Client
All the Client does (even though it is the largest of the classes) is to provide a place to enter a username and password and request the data.
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 70 71 72 | package { import flash.display.Sprite; import flash.text.TextField; import flash.text.TextFormat; import flash.text.TextFieldAutoSize; import fl.controls.Label; import fl.controls.TextArea; import fl.controls.Button; import fl.controls.TextInput; import flash.events.MouseEvent; public class Client extends Sprite { private var proxy:ISubject; private var lblUN:Label=new Label(); private var lblPW:Label=new Label(); private var txt:TextField=new TextField; private var format:TextFormat=new TextFormat; private var txtArea:TextArea=new TextArea(); private var userInput:TextInput=new TextInput(); private var pwInput:TextInput=new TextInput(); private var btn:Button = new Button(); public function Client() { setText(); setIO(); btn.addEventListener(MouseEvent.CLICK, requestTextVars); } private function setText() { format.font="Arial Black"; format.size=24; format.color="0x990000"; txt.defaultTextFormat=format; addChild(txt); txt.autoSize=TextFieldAutoSize.LEFT; txt.text="Protected Proxy"; txt.x=32,txt.y=8; txt.height=24; lblUN.text="User name"; lblUN.x=136,lblUN.y=48; addChild(lblUN); lblPW.text="Password"; lblPW.x=136,lblPW.y=72; addChild(lblPW); btn.x=200, btn.y=72; btn.label= "Show Data"; btn.width=80; addChild(btn); } private function setIO() { addChild(userInput); userInput.x=32,userInput.y=48; addChild(pwInput); pwInput.displayAsPassword=true; pwInput.x=32,pwInput.y=72; addChild(txtArea); txtArea.width=248; txtArea.height=250; txtArea.x=32,txtArea.y=104; } private function requestTextVars(e:MouseEvent) { proxy=new SubProxy(); proxy.pxRequest(txtArea,userInput.text,pwInput.text); } } } |
Using the requestTextVars()method with literals, the whole thing could have been done with three lines, but to be realistic, the Client needs to have user entry—username and password. The TextArea is automatically supplied; so the user simply types in the username and password and clicks the button to request the data. (Little does she know that the request is re-directed to the Proxy.)
No Constructor Functions, Please
You may have noticed that no constructor functions were used in any of the participants. I’ve started leaving out constructor functions unless they have something to do—as is the case with the Client. I have noted in several previous posts that the Google programming standards bearer, Miško Hevery, cautions that constructor functions should do no real work. Here’s why:
When your constructor has to instantiate and initialize its collaborators, the result tends to be an inflexible and prematurely coupled design.
One way to help remember that is not to put them in the participant classes. True, constructor functions are automatically generated if none is placed in a class; however, by leaving out explicit constructor functions I’m not tempted to give them any real work.
In Part II, we’re going to give the Proxy a real workout and several options. Also, instead of a single RealSubject, there will be several. This means that the Proxy is going to have to filter through different levels of access and then select which will be appropriate for the request.
Related posts:


Bill Sanders
Thanks, loved it.
In the “The difficulty I had with this program was trying to return the data.” why not just use your own event that also holds the loaded text?
Hi Gil,
The event handler that loads the text must be called passing the right event object. Also, it cannot be called until I know the text is loaded.
Anyway, I beat my head against the wall, and maybe I’m still missing something. Would you mind sending a code snippet of what you have in mind?
Thanks,
Bill
Creating the new event class:
1. Create a new class named DataLoadedEvent and extend Event class
2. add a new member to the class and name is data
3. in the constructor add a data parameter
Listening to the event:
1. In your Client class, where you created the proxy, listen to this new event.
2. In your event handler, read the data (From the new event class) and put it in the TextArea
Dispatching the event:
1. In your RealSubject in the loadTXT function dispatch this new event with the loaded data.
That’s it
Hi Gil,
Thanks man. Now…one more little thing. The working code.That sounds good, but I’d like to see the code you suggest.
Kindest regards,
Bill
Where can I send it to?
Hi Gil,
You can send it here to the comments section or to me at:
wdsanders@comcast.net
Thanks for taking the time to do this.
Cheers,
Bill
Hi,
instead of passing the the textArea you could pass a responder to the RealSubject. Any error like ArgumentError or SecurityError passes the faultString to the defined fault Method, if the txtLoader completes you simply call the resultHandler method and pass the result String.
How you implement fault and result method inside your subProxy is up to you.
hth?
Christoph
Hi Christoph,
Sounds like a great idea, but did you really try this out? How is this going to happen if the call is to the Proxy? Let’s see some code here.
Earlier Gil had an idea, and he sent some great code (which I’m going to add as a separate post later.) If this will work, I’ll see about putting up a post on it.
Thanks,
Bill
private function requestTextVars(e:MouseEvent)
{
proxy=new SubProxy();
proxy.pxRequest(txtArea,userInput.text,pwInput.text);
}
new SubProxy isn’t required
Hi Ayumilove,
Did you try this out? I did, and it does not work without instantiating a new SubProxy(). The proxy object is typed as an ISubject (program to the interface and not the implementation), and as you know you cannot instantiate an instance of an interface. We don’t want it to be instantiated as a RealSubject, which is also subclassed from ISubject. So, since the Client needs an object I had to instantiate it as an instance of the Proxy class (SubProxy).
Maybe I didn’t understand your point, and if you could clarify, I’d very much appreciate hearing from you.
Kindest regards,
Bill