CSC/ECE 517 Fall 2012/ch2b 2w39 ka: Difference between revisions
Line 198: | Line 198: | ||
===Difference between Decorator and Proxy Pattern=== | ===Difference between Decorator and Proxy Pattern=== | ||
The two UML diagrams may confuse us. The two design patterns looks the same with each other. With Decorator Pattern, the decorator and the decoratee implement the same interfaces. With Proxy Pattern, the proxy class and the real class delegated implement the same interfaces. Furthermore, no matter which pattern is used, it is easy to add functions before or after the method of the real object. | The two UML diagrams may confuse us. The two design patterns looks the same with each other. With Decorator Pattern, the decorator and the decoratee implement the same interfaces. With Proxy Pattern, the proxy class and the real class delegated implement the same interfaces. Furthermore, no matter which pattern is used, it is easy to add functions before or after the method of the real object. | ||
However, in fact, there are some differences between Decorator Pattern and Proxy Pattern. Decorator Pattern focuses on dynamically adding functions to an object, while Proxy Pattern focuses on controlling access to an object. In other words, with Proxy Pattern, the proxy class can hide the detail information of an object from its client. Therefore, when using Proxy Pattern, we usually create an instance of object inside the proxy class. And when using Decorator Pattern, we typically pass the original object as a parameter to the constructor of the decorator. | However, in fact, there are some differences between Decorator Pattern and Proxy Pattern. Decorator Pattern focuses on dynamically adding functions to an object, while Proxy Pattern focuses on controlling access to an object. In other words, with Proxy Pattern, the proxy class can hide the detail information of an object from its client. Therefore, when using Proxy Pattern, we usually create an instance of object inside the proxy class. And when using Decorator Pattern, we typically pass the original object as a parameter to the constructor of the decorator.We can use another sentence to conclude thire differences: | ||
<pre>with the Proxy pattern, the relationship between a proxy and the real subject is typically set at compile time, whereas decorators can be recursively constructed at runtime.</pre> | <pre>with the Proxy pattern, the relationship between a proxy and the real subject is typically set at compile time, whereas decorators can be recursively constructed at runtime.</pre> | ||
Revision as of 17:23, 17 November 2012
Introduction
Describe what Design pattern is and what are we going to discuss in this article.
Decorator Pattern
brief overview
Intent
Problem
Solution
Example
Implementation
Ruby
brief explanation and Sample Code:
type the code here
Java
brief explanation and Sample Code:
type the code here
Adapter Pattern
brief overview
Intent
Problem
Solution
Example
Implementation
Ruby
brief explanation and Sample Code:
type the code here
Java
brief explanation and Sample Code:
type the code here
Proxy Pattern
Sometimes we need the ability to control the access to an object. For example if we need to use only a few methods of some costly objects we'll initialize those objects when we need them entirely. Until that point we can use some light objects exposing the same interface as the heavy objects. These light objects are called proxies and they will instantiate those heavy objects when they are really need and by then we'll use some light objects instead.
Intent
Provide a surrogate or placeholder for another object to control access to it” is the intent provided by GoF<ref>"Gang of four"</ref>
Problem
You need to support resource-hungry objects, and you do not want to instantiate such objects unless and until they are actually requested by the client.
Solution
Design a surrogate, or proxy, object that: instantiates the real object the first time the client makes a request of the proxy, remembers the identity of this real object, and forwards the instigating request to this real object. Then all subsequent requests are simply forwarded directly to the encapsulated real object.
Let's take a look at the diagram definition before we go into more detail.
As usual, when dealing with design patterns we code to interfaces. In this case, the interface that the client knows about is the Subject. Both the Proxy and RealSubject objects implement the Subject interface, but the client may not be able to access the RealSubject without going through the Proxy. It's quite common that the Proxy would handle the creation of the RealSubject object, but it will at least have a reference to it so that it can pass messages along.
Let's take a look at this in action with a sequence diagram.
As you can see it's quite simple - the Proxy is providing a barrier between the client and the real implementation.
There are many different flavours of Proxy, depending on it's purpose. You may have a protection proxy, to control access rights to an object. A virtual proxy handles the case where an object might be expensive to create, and a remote proxy controls access to a remote object.
You'll have noticed that this is very similar to the Adapter pattern. However, the main difference between bot is that the adapter will expose a different interface to allow interoperability. The Proxy exposes the same interface, but gets in the way to save processing time or memory.
Example
There are four common situations in which the Proxy pattern is applicable.
- A virtual proxy is a placeholder for “expensive to create” objects.
The real object is only created when a client first requests/accesses the object. In place of a complex or heavy object use a skeleton representation. When an underlying image is huge in size, just represent it using a virtual proxy object and on demand load the real object. You feel that the real object is expensive in terms of instantiation and so without the real need we are not going to use the real object. Until the need arises we will use the virtual proxy.
- A remote proxy provides a local representative for an object that resides in a different address space.
This is what the “stub” code in RPC and CORBA provides. Think of an ATM implementation, it will hold proxy objects for bank information that exists in the remote server. RMI is an example of proxy implmenetation for this type in java.
- A protective proxy controls access to a sensitive master object.
The “surrogate” object checks that the caller has the access permissions required prior to forwarding the request. You might be well aware of the proxy server that provides you internet. Saying more than provides, the right word is censores internet. The management feels its better to censor some content and provide only work related web pages. Proxy server does that job. This is a type of proxy design pattern. Lighter part of censor is, we search for something critical in Google and click the result and you get this page is blocked by proxy server. You never know why this page is blocked and you feel this is genuine. How do you overcome that, over a period you learn to live with it.
- A smart proxy interposes additional actions when an object is accessed. Typical uses include:
- Counting the number of references to the real object so that it can be freed automatically when there are no more references (aka smart pointer),
- Loading a persistent object into memory when it’s first referenced,
- Checking that the real object is locked before it is accessed to ensure that no other object can change it.
Implementation
Ruby
Let’s assume you need to log all method calls made to a bank Account object without changing the original Account definition. You can create a new class to wrap the Account object, log any method call then forward the request to the target object. Here’s a super simple bank Account.
class Account def initialize(amount) @amount = amount end def deposit(amount) @amount += amount end def withdraw(amount) @amount -= amount end def balance @amount end def inspect puts "Amount: #{@amount}" end end
and here’s our AccountLogger class.
class AccountLogger < BasicObject def initialize(amount) @operations = [] @target = Account.new(amount) @operations << [:initialize, [amount]] end def method_missing(method, *args, &block) @operations << [method, args] @target.send(method, *args, &block) end def operations @operations end end
The AccountLogger is our Proxy object. It doesn’t know anything about the target object, in fact it limits itself to log method calls and forward the request to the underlying @target using the method_missing hook.BasicObject actually prevents this issue by exposing a limited set of instance methods. Simply put, it copes with the problem from a different point of view: instead of taking a rich object and removing all the unnecessary methods, take a poor object and only define what you actually need.
Java
From JDK 1.3 java has direct support for implementing proxy design pattern. We need not worry on mainting the reference and object creation. Java provides us the needed utilities. Following example implementation explains on how to use java’s api for proxy design pattern.
public interface Animal { public void getSound(); }
public class Lion implements Animal { public void getSound() { System.out.println("Roar"); } }
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class AnimalInvocationHandler implements InvocationHandler { public AnimalInvocationHandler(Object realSubject) { this.realSubject = realSubject; } public Object invoke(Object proxy, Method m, Object[] args) { Object result = null; try { result = m.invoke(realSubject, args); } catch (Exception ex) { ex.printStackTrace(); } return result; } private Object realSubject = null; }
import java.lang.reflect.Proxy; public class ProxyExample { public static void main(String[] args) { Animal realSubject = new Lion(); Animal proxy = (Animal) Proxy.newProxyInstance(realSubject.getClass() .getClassLoader(), realSubject.getClass().getInterfaces(), new AnimalInvocationHandler(realSubject)); proxy.getSound(); } }
We have created a proxy handler that will be able to get the sound depending on the type of animal.
Difference between Decorator and Proxy Pattern
The two UML diagrams may confuse us. The two design patterns looks the same with each other. With Decorator Pattern, the decorator and the decoratee implement the same interfaces. With Proxy Pattern, the proxy class and the real class delegated implement the same interfaces. Furthermore, no matter which pattern is used, it is easy to add functions before or after the method of the real object. However, in fact, there are some differences between Decorator Pattern and Proxy Pattern. Decorator Pattern focuses on dynamically adding functions to an object, while Proxy Pattern focuses on controlling access to an object. In other words, with Proxy Pattern, the proxy class can hide the detail information of an object from its client. Therefore, when using Proxy Pattern, we usually create an instance of object inside the proxy class. And when using Decorator Pattern, we typically pass the original object as a parameter to the constructor of the decorator.We can use another sentence to conclude thire differences:
with the Proxy pattern, the relationship between a proxy and the real subject is typically set at compile time, whereas decorators can be recursively constructed at runtime.
Composite Pattern
brief overview
Intent
Problem
Solution
Example
Implementation
Ruby
brief explanation and Sample Code:
type the code here
Java
brief explanation and Sample Code:
type the code here
Comparison of the Patterns
Comparison | Decorator | Adapter | Proxy | Composite |
---|---|---|---|---|
Supports abc | ||||
Supports def | ||||
Supports ghi | ||||
Supports bla | ||||
Supports bla |
Conclusion
This article makes an attempt to explain the concept of Reflection in Object Oriented Programming. The article mentions the different approaches to reflection in Ruby and other languages.It mentions the usage of Reflections and the advantages and disadvantages of using Reflection. A follow up to this article would be to study the concept of Metaprogramming.
References
<references />