The proxy pattern is used when you need to represent a complex with a simpler one. If creation of object is expensive, its creation can be postponed till the very need arises and till then, a simple object can represent it. This simple object is called the “Proxy” for the complex object
Definition
Use a simple object to represent a complex one or provide a placeholder for another object to control access to it.Intent
01- Provide a surrogate or placeholder for another object to control access to it.
- Use an extra level of indirection to support distributed, controlled, or intelligent access.
- Add a wrapper and delegation to protect the real component from undue complexity.
Problem
02You 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.
Where to use & benefits
- If creating an object is too expensive in time or memory.
- Postpone the creation until you need the actual object.
- Load a large image (time consuming).
- Load a remote object over network during peak periods.
- Access right is required to a complex system.
- Related patterns include
- Adapter pattern, which provides a different interface to the object it adapts, whereas a proxy provides the same interface as its subject, and
- Decorator pattern, which focuses on adding new functions to an object, whereas a proxy controls access to the object.
Structure
06By defining a Subject interface, the presence of the Proxy object standing in place of the RealSubject is transparent to the client.
Intent
- The intent of this pattern is to provide a “Placeholder” for an object to control references to it.
Implementation
The figure below shows a UML class diagram for the Proxy Pattern:Example
07The Proxy provides a surrogate or place holder to provide access to an object. A check or bank draft is a proxy for funds in an account. A check can be used in place of cash for making purchases and ultimately controls access to cash in the issuer’s account.
Bank.java
Also, the second class is ATMProxy. This also defines the way the transaction can be handled for withdrawal of money.
ATMProxy.java
Here, we can also create another proxy called ChequeProxy. I am not creating it here as the message I wanted to send across has been conveyed with the help of one proxy only. We can see here that creation of object of Bank is very costly, effort and time wise, and so, we can as well use a proxy called ATM to get the result. ATM can internally communicate with the Bank object. So, ATM here is also acting like a façade.
This might and might not happen. It can happen that we at a later stage have to create the same heavy object. We just want to postpone the creation of object to the last minute so that the application is not loaded by resources utilized for creating the object.
package structural.proxy; /** * Bank.java * The class acts as the main object for which * the proxy has to be created. As described, going * to bank for withdrawal is very costly time wise. */ public class Bank { | ||
private int numberInQueue; /** * Method getMoneyForPurchase * This method is responsible for the entire banking * operation described in the write-up */ public double getMoneyForPurchase(double amountNeeded) { // get object for person You you = new You("Prashant"); // get obj for account Account account = new Account(); // get person's account number String accountNumber = you.getAccountNumber(); // passbook got. boolean gotPassbook = you.getPassbook(); // get number in queue int number = getNumberInQueue(); // the number will decrease every few mins while (number != 0) { number--; } // now when the number = 0, check if balance is sufficient boolean isBalanceSufficient = account.checkBalance(accountNumber, amountNeeded); if(isBalanceSufficient) return amountNeeded; else return 0; } /** * returns the number in the queue */ private int getNumberInQueue() { return numberInQueue; } | ||
}// End of class |
ATMProxy.java
package structural.proxy; public class ATMProxy { | ||
/** * Method getMoneyForPurchase * This method is responsible for the entire banking * operation described in the write-up */ public double getMoneyForPurchase(double amountNeeded) { // get obj of You to get card You you = new You("Prashant"); // get obj for account Account account = new Account(); boolean isBalanceAvailable = false; // if card there, go ahead if(you.getCard()) { isBalanceAvailable = account.checkBalance(you.getAccountNumber(), amountNeeded); } if(isBalanceAvailable) return amountNeeded; else return 0; } | ||
}// End of class |
This might and might not happen. It can happen that we at a later stage have to create the same heavy object. We just want to postpone the creation of object to the last minute so that the application is not loaded by resources utilized for creating the object.
Proxy design pattern
01- Create a “wrapper” for a remote, or expensive, or sensitive target
- Encapsulate the complexity/overhead of the target in the wrapper
- The client deals with the wrapper
- The wrapper delegates to the target
- To support plug-compatibility of wrapper and target, create an interface
import java.io.*; import java.net.*;
// 5. To support plug-compatibility between
// the wrapper and the target, create an interface
interface SocketInterface {
String readLine();
void writeLine( String str );
void dispose();
}
public class ProxyDemo {
public static void main( String[] args ) {
// 3. The client deals with the wrapper
SocketInterface socket = new SocketProxy( "127.0.0.1", 8189,
args[0].equals("first") ? true : false );
String str = null;
boolean skip = true;
while (true) {
if (args[0].equals("second") && skip) {
skip = ! skip;
}
else {
str = socket.readLine();
System.out.println( "Receive - " + str ); // java ProxyDemo first
if (str.equals("quit")) break; // Receive - 123 456
} // Send ---- 234 567
System.out.print( "Send ---- " ); // Receive - 345 678
str = Read.aString(); //
socket.writeLine( str ); // java ProxyDemo second
if (str.equals("quit")) break; // Send ---- 123 456
} // Receive - 234 567
socket.dispose(); // Send ---- 345 678
}
}
class SocketProxy implements SocketInterface {
// 1. Create a "wrapper" for a remote,
// or expensive, or sensitive target
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public SocketProxy( String host, int port, boolean wait ) {
try {
if (wait) {
// 2. Encapsulate the complexity/overhead of the target in the wrapper
ServerSocket server = new ServerSocket( port );
socket = server.accept();
} else
socket = new Socket( host, port );
in = new BufferedReader( new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter( socket.getOutputStream(), true );
} catch( IOException e ) {
e.printStackTrace();
}
}
public String readLine() {
String str = null;
try {
str = in.readLine();
} catch( IOException e ) {
e.printStackTrace();
}
return str;
}
public void writeLine( String str ) {
// 4. The wrapper delegates to the target
out.println( str );
}
public void dispose() {
try {
socket.close();
} catch( IOException e ) {
e.printStackTrace();
}
}
}
No comments:
Post a Comment