8.代理模式
代理模式跟装饰器模式好像,只不过设计目的不同。
静态代理
下面这个例子来自——菜鸟教程
public interface Image {
void display();
}
public class RealImage implements Image {
private String fileName;
public RealImage(String fileName){
this.fileName = fileName;
loadFromDisk(fileName);
}
@Override
public void display() {
System.out.println("Displaying " + fileName);
}
private void loadFromDisk(String fileName){
System.out.println("Loading " + fileName);
}
}
public class ProxyImage implements Image{
private RealImage realImage;
private String fileName;
public ProxyImage(String fileName){
this.fileName = fileName;
}
@Override
public void display() {
if(realImage == null){
realImage = new RealImage(fileName);
}
realImage.display();
}
}
public class ProxyPatternDemo {
public static void main(String[] args) {
Image image = new ProxyImage("test_10mb.jpg");
// 图像将从磁盘加载
image.display();
System.out.println("");
// 图像不需要从磁盘加载
image.display();
}
}
看到这儿看起来很眼熟对吧,这个实现上跟装饰器模式几乎没区别把。
装饰器是为了增加新的功能或者删除已有的功能而实现的,这些功能与目标功能类似,比如宝马汽车可以飞。代理模式则是把任务交给建立的对象来做,实现一些不同的功能,比如增加日志。
输出
Loading test_10mb.jpg
Displaying test_10mb.jpg
Displaying test_10mb.jpg
以上说的是静态代理。
那为啥叫静态代理呢?咱们看看动态代理。
动态代理
所谓的动态代理就是在程序运行中,动态的建立代理类。
看以下例子
public interface Image {
void display();
}
public class RealImage implements Image {
private String fileName;
public RealImage(String fileName){
this.fileName = fileName;
loadFromDisk(fileName);
}
@Override
public void display() {
System.out.println("Displaying " + fileName);
}
private void loadFromDisk(String fileName){
System.out.println("Loading " + fileName);
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ImageInovationHandler implements InvocationHandler {
private RealImage realImage;
public ImageInovationHandler(RealImage realImage) {
this.realImage = realImage;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//添加处理日志啊啥的
//System.out.println();
method.invoke(realImage,args);
return null;
}
}
public class Client {
public static void main(String[] args) {
RealImage realImage = new RealImage("test_10mb.jpg");
InvocationHandler imageInvocationHandler = new ImageInovationHandler( realImage);
//通过反射得到RealImage的代理对象
Image realImageProxy = (Image) Proxy.newProxyInstance(realImage.getClass().getClassLoader(), realImage.getClass().getInterfaces(), imageInvocationHandler);
//调用display方法
realImageProxy.display();
}
}
动态代理使用了java自带的接口和类。
把所有的代理类都交给InvocationHandler的实现类处理。Proxy通过反射,动态地建立代理对象,调用所需要调用的方法。
所谓的动态代理就是在程序运行中,动态的建立代理类。
可以看出,如果使用静态代理,给每个想代理的对象都增加日志功能,那么就需要给每个想要被代理的对象书写代理类,而动态代理 ,只需要写一个代理类,就可以给每个想代理增加日志功能。