现实生活中代理很常见,在设计领域代理模式也经常被使用,它的意义在于为其他对象提供代理层以控制对这个对象的访问
使用场景
当某个接口不方便直接被调用时,就考虑使用代理模式对其进行封装,并添加必要的控制逻辑,如:
- 权限控制,即在特定逻辑处插入权限控制代码
- 对象保护,即客户端不能直接操纵某对象,但又必须与该对象有所交互
代码示例
代理分为静态代理与动态代理两种。这里的静态与动态和软件开发里经常提及的静态/动态意思相近,即前者代表死的,后者代表活的,啥意思呢?即:静态代理一次只能代理一个业务实现,针对多个业务实现就需要多个静态代理类进行代理;而动态代理类可以对同一接口下一系列的业务实现进行统一代理,增加了灵活性,如大名鼎鼎的AOP(面向切面编程)其实现机制就是动态代理
静态代理:
//被代理接口
public interface Image {
public void loadImage();
}
//被代理实现
public class ViewImage implements Image{
@Override
public void loadImage() {
System.out.println("ViewImage load image");
}
}
//代理类
public class ImageProxy implements Image{
private Image targetImage;
public ImageProxy(Image targetImage) {
this.targetImage = targetImage;
}
@Override
public void loadImage() {
System.out.println("ImageProxy begin");
this.targetImage.loadImage();
System.out.println("ImageProxy ends");
}
}
//客户端调用
public class ImageClient {
public static void main(String[] args) {
ImageProxy imageProxy = new ImageProxy(new ViewImage());
imageProxy.loadImage();
}
}
//运行结果
ImageProxy begin
ViewImage load image
ImageProxy ends
增加代理后,可以方便的在被代理的业务逻辑前后增加控制逻辑;
动态代理:
//被代理接口
public interface Image {
public void loadImage();
}
//被代理实现
public class PersonImage implements Image {
@Override
public void loadImage() {
System.out.println("PersonImage load image");
}
}
//被代理实现
public class ViewImage implements Image {
@Override
public void loadImage() {
System.out.println("ViewImage load image");
}
}
//代理类
public class ImageHandler implements InvocationHandler{
private Object target;
public Object getProxy(Object target) {
this.target = target;
Object result = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
return result;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("ImageHandler begin");
Object result = null;
try{
result = method.invoke(this.target,args);
}catch(Exception e){
e.printStackTrace();
}
return result;
}
}
//客户端调用
public class ImageClient {
public static void main(String[] args) {
ImageHandler imageHandler = new ImageHandler();
Image personImageProxy = (Image)imageHandler.getProxy(new PersonImage());
Image viewImageProxy = (Image)imageHandler.getProxy(new ViewImage());
personImageProxy.loadImage();
viewImageProxy.loadImage();
}
}
//运行结果
ImageHandler begin
ViewImage load image
ImageHandler begin
ViewImage load image
上例是通过Java本身提供的针对动态代理的支持接口进行实现,实现其接口即可达到动态代理的效果,当然,除开通过JDK实现动态代理,比较常用的动态代理实现方式还有通过CGLIB,这里就不做详细介绍