ActionScript Proxy Design Pattern : The Virtual Proxy (A Minimal Abstract Example)

The Gang of Four divide up the Proxy design pattern into three types: remote, virtual, and protection. In our book, Chandima and I used a remote proxy in the Symmetric Proxy example(Chapter 13). Each player in a game over the Internet was able to make simultaneous moves using the remote proxy representing an opponent on their own system. That leaves the virtual and protection proxies to cover, and we’ll start with the virtual proxy in this article.

Avoiding Repetition

Our university uses a software package called Blackboard for course administration. It’s quite handy, and I use it a good deal. As a Web-based application requiring a login, the initial login is time-consuming as the application gathers up all of the information it has stored for all of my classes. However, if I quit the program and return within a certain time window, I don’t have to go through login again. More importantly, the application does not have to reload all of the materials for me again. When you consider that hundreds of faculty and thousands of students are all using the same system on a daily basis, the ability to re-use previously loaded materials is a huge savings.

For the most part, design patterns, do not improve the performance of your programs with a few exceptions, such as the Flyweight pattern previously discussed on this blog. I believe that the virtual proxy design pattern is another one of those patterns that improves the performance of your program because your application is not constantly re-doing something expensive (time-consuming) that’s already been done. Most of the examples, including the one provided by GoF, are of loading graphics. Once loaded, most graphics do not have to be reloaded for repeated display after the initial loading. So, rather than reload graphics or files of any kind, the virtual proxy design first checks to see if your materials are already loaded, and if they are, it uses the extant materials. If not, it simply calls the real loader and loads up what’s required. Any application that has multiple users over the Web (which is most programs) the virtual proxy can significantly improve the performance of the program because it reuses loaded materials.

How the Proxy Design Pattern Works

The Proxy pattern does not have different class diagrams for the different types of proxies. Figure 1 shows the pattern diagram used for all variations of the pattern.


Figure 1: Proxy Class Diagram

The client is not a participant, but it is included to indicate where it sends its request. It is loosely coupled to the participants following the path illustrated in Figure 2.


Figure 2: Proxy Object Diagram

The proxy is used to check and see if a real subject is required, and if so, it sends the request to the real subject. However, if the proxy can handle the request without using the real subject, it will do so. In effect, the proxy acts like a gatekeeper. It inspects all requests, and if it can deal with the requests it does, but no requests go directly to the real subject from the client. Figure 2 shows the intermediary position of the proxy. The only problem with the object diagram is that it looks like the proxy is a stop along the way to the real subject, but depending on the application, the request may never get to the real subject.

A Login Example

The login example stemmed from my experiences with Blackboard. The ease with which I am able to “re-log” without having to wait for a total reload is the driving rationale behind this abstract, virtual proxy design pattern. It is simple, yet informative both as an example of good OOP and design patterns.

To get started, I put together a class diagram with the classes I planned to use reflecting the Proxy design pattern as shown in Figure 3:


Figure 3

The client instantiates a ProxyLogin typed as ISecurity, the interface. The proxy instance checks the username to see if the user is logged in; if so, it executes the login method that indicates that the user is already logged in. Otherwise, the proxy instantiates an instance of the RealLogin class, and it loads everything that needs loading and then informs the user that the login has been successful.

The Subject Interface, Proxy and Real Deal

First, the Subject class is an interface, ISecurity. It has a single method as the first listing shows:

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
package 
{
	public interface ISecurity
	{
		function login():void;
	}
}

Next, the Proxy class, LoginProxy, checks to see if the user is logged in. by checking the object containing login information:

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package 
{
public class ProxyLogin implements ISecurity
	{
		private var username:String;
		private var loggedIn:ISecurity;
 
		public function ProxyLogin(username:String)
		{
			this.username=username;
		}
		public function login():void
		{
			if (loggedIn==null)
			{
				loggedIn=new RealLogin(username);
			}
			loggedIn.login();
		}
	}
}

Now, the proxy will use a RealLogin object and its operations only if it finds that no object with the username has logged in. It instantiates a new instance of RealLogin() with the username as a parameter. So let’s see what happens next:

?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
package 
{
	public class RealLogin implements ISecurity
	{
		private var username:String;
 
		public function RealLogin(username:String)
		{
			this.username=username;
			doLogin();
		}
 
		private function doLogin():void
		{
			trace("Connect "+username+" to server");
			trace("Check "+username+"'s credentials");
			trace("Load data from database for "+username);
			trace("Compare "+username+"'s IP with banned list");
			trace("Verify "+username+"'s security level \n");
		}
 
		public function login():void
		{
			trace(username + " has logged in.\n");
		}
	}
}

All of trace() statements in the doLogin() method represent heavy lifting by the application. The whole point is to avoid the doLogin() method if at all possible by re-using an existing login through the Proxy participant. After each login, the login() method indicates who has logged in.

The Client

The client requests a login by instantiating a ProxyLogin object. Then each object makes a request through the login() method. Because none have logged in initially, the ProxyLogin must invoke the RealLogin . To simulate re-logging in after a user is currently logged in, the client (SecurityProxy), one of the users (steve) logs in multiple times. However, as you will see, after the first login, repeat logins are free in that the materials generated initially no longer require the RealLogin.

?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
package 
{
	import flash.display.Sprite;
 
	public class SecurityProxy extends Sprite
	{
		private var bill:ISecurity;
		private var steve:ISecurity;
		private var stephen:ISecurity;
 
		public function SecurityProxy()
		{
			bill=new ProxyLogin("Gates");
			steve=new ProxyLogin("Jobs");
			stephen=new ProxyLogin("Hawking");
 
			bill.login();
			steve.login();
			steve.login();
			stephen.login();
			steve.login();
		}
	}
}

Note where the \n is placed to force an additional linefeed. That’s to separate the login announcement from all of the chores required to login. When all you see is repeated login announcement without all of the trace statements, it indicates that the user has re-logged. The following output is generated by the client’s request:

Connect Gates to server
Check Gates's credentials
Load data from database for Gates
Compare Gates's IP with banned list
Verify Gates's security level

Gates has logged in.

Connect Jobs to server
Check Jobs's credentials
Load data from database for Jobs
Compare Jobs's IP with banned list
Verify Jobs's security level

Jobs has logged in.

Jobs has logged in.

Connect Hawking to server
Check Hawking's credentials
Load data from database for Hawking
Compare Hawking's IP with banned list
Verify Hawking's security level

Hawking has logged in.

Jobs has logged in.

Note that instances bill (“Gates”) and stephen (“Hawking”) log in only once. However, steve (“Jobs”) logs in two additional times after an initial login. The logins after the initial ones show the value of the virtual proxy design. All of the other tasks for login are not repeated, but instead the user is logged in without additional work by the RealLogin object.

8 Responses to “ActionScript Proxy Design Pattern : The Virtual Proxy (A Minimal Abstract Example)”


Leave a Reply