introduce
Intent : Provide a stand-in or placeholder for another object to control access to this object.
The main solution : the problem caused by directly accessing the object, for example: the object to be accessed is on a remote machine. In object-oriented systems, for some reasons (such as object creation is expensive, or some operations require security control, or require out-of-process access), direct access will bring a lot of trouble to users or system structures. We can add an access layer to this object when accessing this object.
When to use : Want to do some control when accessing a class.
How to fix : Add middle layers.
Key code : implementation and proxy class combination.
accomplish
A mock loading image implementation class
Basic implementation
public interface Image {
void display();
}
proxied class
public class RealImage implements Image {
private String fileName;
public RealImage(String fileName) {
this.fileName = fileName;
}
[@Override](https://my.oschina.net/u/1162528)
public void display() {
System.out.println("Displaying " + fileName);
try {
Thread.sleep(666);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Proxy class - used to calculate the time spent by diplay()
public class ProxyImage implements Image {
private RealImage realImage;
private String fileName;
public ProxyImage(String fileName) {
this.fileName = fileName;
}
[@Override](https://my.oschina.net/u/1162528)
public void display() {
long begin = System.currentTimeMillis();
if (realImage == null) {
realImage = new RealImage(fileName);
}
realImage.display();
long end = System.currentTimeMillis();
System.out.println("It's spent " + (end - begin)+ "ms");
}
}
run class
public class ProxyPatternDemo {
public static void main(String[] args) {
Image image = new ProxyImage("18stop.jpg");
image.display();
}
}
operation result
Displaying 18stop.jpg
It's spent 670ms
JDK dynamic proxy
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import designpattern.proxy.example1.Image;
import designpattern.proxy.example1.RealImage;
public class TimerHandler implements InvocationHandler {
private Object target;
public TimerHandler(Object target) {
this.target = target;
}
[@Override](https://my.oschina.net/u/1162528)
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long begin = System.currentTimeMillis();
Object obj = method.invoke(target, args);
long end = System.currentTimeMillis();
System.out.println("It's spent " + (end - begin)+ "ms");
return obj;
}
public static void main(String[] args) {
RealImage image = new RealImage("18stop.jpg");
TimerHandler timer = new TimerHandler(image);
Image proxyImage = (Image)Proxy.newProxyInstance(
image.getClass().getClassLoader(),
image.getClass().getInterfaces(),
timer);
proxyImage.display();
}
}
operation result
Displaying 18stop.jpg
It's spent 675ms
References and citations
1. "Head First Design Patterns" Eric Freeman et al