Design Pattern: Proxy Pattern
The OS X Dictionary app says that proxy is a noun meaning:
a figure that can be used to represent the value of something in a calculation
… and there you have it, the Proxy pattern. Make a ProxySomething class that can represent your Something class and you’re done.
Ok, maybe it’s not that simple, but it’s not that complex either. I’ve been giving Olsen a lot of props for his well-worded one-line descriptions of many of the patterns but I’m going to tip my hat to the Gang of Four on this one. They describe a proxy as something that “controls access to an object” (p 216), and that pretty much encapsulates how proxies are used.
Here’s a quick code sample of our Something class and how you’d set up your SomethingProxy.
class Something
def awesome_method
...some cool behavior...
end
end
class SomethingProxy
def initialize(something_object)
@object = something_object
end
def awesome_method
@object.awesome_method
end
end
Now if you were to instantiate a new proxy object you could do it like this
proxy_object = SomethingProxy.new(an_actual_something_object)
and if you were to call the awesome_method
on your proxy_object it would perform the cool behavior that we defined in the Something class.
The important thing is that your proxy has the same interface as the actual object. Olsen even dives into metaprogramming and how you can overwrite the default Ruby method_missing
to forward any method that isn’t defined in your Proxy class to the actual object, but I have a feeling that I’ll steer clear of using it much. It seems like blindly passing on messages and arguments would obfuscate the intention of the code and break some of the rules I covered from the second Clean Coders episode.
There are three common ways that are proxies are implemented:
1) A protection proxy
2) A remote proxy
3) A virtual proxy
The first two proxies do just what they sound like. The protection proxy is used to literally control who and what has access to your actual object. Every method call to your object could first be run through a confirm_access method in your proxy, so you could even limit certain methods to certain users or objects. The added benefit is that it separates all of the security concerns out of the object itself.
The remote proxy is used when you want something to stand in for an object that exists somewhere else. The easiest example to think of is if there were an object that existed on a server somewhere far away, and you could create a proxy for that client to use locally.
Last is the virtual proxy. The virtual proxy is used when the creation or modification of your actual object is very expensive (think in terms of CPU, storage, RAM, security). The virtual proxy is the closest a proxy will get to being the actual object because for all intents and purposes it has all the responsibilities of the real object until is explicitly told to create the real object and pass off that responsibility.
The proxy pattern is another one that I’ll be looking for out in the wild. I can definitely see where they can be effective in web applications.