代理模式

 代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,如图1所示。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。


图1:Proxy模式

 

按照代理类的创建时期,代理类可分为两种。

  • 静态代理类:由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
  • 动态代理类:在程序运行时,运用反射机制动态创建而成。

 

静态代理类的实现:

 

1. 定义一个IService接口

Java代码 复制代码  收藏代码
  1. package cn.lettoo.proxy;   
  2.   
  3. public interface IService {   
  4.   
  5.     void execute();   
  6. }  
package cn.lettoo.proxy;

public interface IService {

    void execute();
}

 

2. 具体的实现类:

Java代码 复制代码  收藏代码
  1. package cn.lettoo.proxy;   
  2.   
  3. public class PrintService implements IService {   
  4.   
  5.     public void execute() {   
  6.         System.out.println("The Print Service works.");   
  7.     }   
  8. }  
package cn.lettoo.proxy;

public class PrintService implements IService {

    public void execute() {
        System.out.println("The Print Service works.");
    }
}

 

3. 代理类:

Java代码 复制代码  收藏代码
  1. package cn.lettoo.proxy;   
  2.   
  3. public class PrintServiceProxy implements IService {   
  4.   
  5.     IService printSerivce;   
  6.   
  7.     public PrintServiceProxy(IService service) {   
  8.         this.printSerivce = service;   
  9.     }   
  10.   
  11.     public void setPrintSerivce(IService printSerivce) {   
  12.         this.printSerivce = printSerivce;   
  13.     }   
  14.   
  15.     public void execute() {   
  16.         this.beforePrint();   
  17.         this.printSerivce.execute();   
  18.         this.afterPrint();   
  19.     }   
  20.   
  21.     private void beforePrint() {   
  22.         System.out.println("Before print.");   
  23.     }   
  24.   
  25.     private void afterPrint() {   
  26.         System.out.println("Before print.");   
  27.     }   
  28.   
  29. }  
package cn.lettoo.proxy;

public class PrintServiceProxy implements IService {

    IService printSerivce;

    public PrintServiceProxy(IService service) {
        this.printSerivce = service;
    }

    public void setPrintSerivce(IService printSerivce) {
        this.printSerivce = printSerivce;
    }

    public void execute() {
        this.beforePrint();
        this.printSerivce.execute();
        this.afterPrint();
    }

    private void beforePrint() {
        System.out.println("Before print.");
    }

    private void afterPrint() {
        System.out.println("Before print.");
    }

}

    代理类的execute()方法只是调用了被代理的Service的execute方法,被代理的Service通过构造函数或者set的方式被注入到代理对象中。同时,代理对象也有一些自己的代理方法,如本例中在被代理类的execute()方法调用前后加上自己的方法。

 

4. 客户调用代码:

Java代码 复制代码  收藏代码
  1. package cn.lettoo.proxy;   
  2.   
  3. public class Client {   
  4.   
  5.     public static void main(String[] args) {   
  6.         IService service = new PrintService();   
  7.         IService proxy = new PrintServiceProxy(service);   
  8.   
  9.         proxy.execute();   
  10.     }   
  11. }  
package cn.lettoo.proxy;

public class Client {

    public static void main(String[] args) {
        IService service = new PrintService();
        IService proxy = new PrintServiceProxy(service);

        proxy.execute();
    }
}

 

执行结果
Before print.
The Print Service works.
Before print.

 

 动态代理的实现:

 

与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。

 

Proxy类提供了创建动态代理类及其实例的静态方法。

Porxy有两种方式来生成代理对象:

方法1:

Java代码 复制代码  收藏代码
  1. //创建InvocationHandler对象   
  2. InvocationHandler handler = newMyInvocationHandler(...);   
  3. //创建动态代理类,IService是被代理的接口   
  4. Class proxyClass = Proxy.getProxyClass(IService.class.getClassLoader(), new Class[] { IService.class });   
  5. //创建动态代理类的实例   
  6. IService proxyService = (IService) proxyClass.getConstructor(new Class[] { invocationHandler.class }).newInstance(new Object[] { handler });  
//创建InvocationHandler对象
InvocationHandler handler = newMyInvocationHandler(...);
//创建动态代理类,IService是被代理的接口
Class proxyClass = Proxy.getProxyClass(IService.class.getClassLoader(), new Class[] { IService.class });
//创建动态代理类的实例
IService proxyService = (IService) proxyClass.getConstructor(new Class[] { invocationHandler.class }).newInstance(new Object[] { handler });

方法2:

Java代码 复制代码  收藏代码
  1. //创建InvocationHandler对象   
  2. InvocationHandler handler = newMyInvocationHandler(...);   
  3. //直接创建动态代理类的实例   
  4. IService serviceProxy = (IService) Proxy.newProxyInstance(IService.class.getClassLoader(), new Class[] { IService.class },   
  5. handler);  
//创建InvocationHandler对象
InvocationHandler handler = newMyInvocationHandler(...);
//直接创建动态代理类的实例
IService serviceProxy = (IService) Proxy.newProxyInstance(IService.class.getClassLoader(), new Class[] { IService.class },
handler);

 

InvocationHandler 接口为方法调用接口,它声明了负责调用任意一个方法的invoke()方法:

Java代码 复制代码  收藏代码
  1. Object invoke(Object proxy,Method method,Object[] args) throws Throwable  
Object invoke(Object proxy,Method method,Object[] args) throws Throwable

 

代码实现:

1. 写一个ServiceFactory,用于生成代理对象

Java代码 复制代码  收藏代码
  1. package cn.lettoo.proxy;   
  2.   
  3. import java.lang.reflect.InvocationHandler;   
  4. import java.lang.reflect.Method;   
  5. import java.lang.reflect.Proxy;   
  6.   
  7. public class ServiceFactory {   
  8.   
  9.     public static IService getServiceProxy(final IService service) {   
  10.         InvocationHandler handler = new InvocationHandler() {   
  11.   
  12.             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {   
  13.                 beforePrint();   
  14.                 Object result = method.invoke(service, args);   
  15.                 afterPrint();   
  16.                 return result;   
  17.             }   
  18.         };   
  19.   
  20.         return (IService) Proxy.newProxyInstance(IService.class.getClassLoader(), new Class[] { IService.class },   
  21.                                                  handler);   
  22.     }   
  23.        
  24.     private static void beforePrint() {   
  25.         System.out.println("Before print.");   
  26.     }   
  27.   
  28.     private static void afterPrint() {   
  29.         System.out.println("Before print.");   
  30.     }   
  31.        
  32. }  
package cn.lettoo.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ServiceFactory {

    public static IService getServiceProxy(final IService service) {
        InvocationHandler handler = new InvocationHandler() {

            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                beforePrint();
                Object result = method.invoke(service, args);
                afterPrint();
                return result;
            }
        };

        return (IService) Proxy.newProxyInstance(IService.class.getClassLoader(), new Class[] { IService.class },
                                                 handler);
    }
    
    private static void beforePrint() {
        System.out.println("Before print.");
    }

    private static void afterPrint() {
        System.out.println("Before print.");
    }
    
}

 

2. 客户端代码:

Java代码 复制代码  收藏代码
  1. package cn.lettoo.proxy;   
  2.   
  3. public class Client {   
  4.   
  5.     public static void main(String[] args) {   
  6.         IService service = new PrintService();           
  7.         IService proxy = ServiceFactory.getServiceProxy(service);           
  8.         proxy.execute();   
  9.     }   
  10.   
  11. }  
package cn.lettoo.proxy;

public class Client {

    public static void main(String[] args) {
        IService service = new PrintService();        
        IService proxy = ServiceFactory.getServiceProxy(service);        
        proxy.execute();
    }

}

 

运行结果
Before print.
The Print Service works.
Before print.
 

 

    也许有人要问,采用动态代理有什么好处?那么我告诉你,你不需要为每个IService的实现类都去写一个Proxy类了(前提是代理方法是一样的),假如,我现在有另外一个IService的实现类如下:

Java代码 复制代码  收藏代码
  1. package cn.lettoo.proxy;   
  2.   
  3. public class AnotherService implements IService {   
  4.   
  5.     public void execute() {   
  6.         System.out.println("I am another service.");   
  7.     }   
  8.   
  9. }  
package cn.lettoo.proxy;

public class AnotherService implements IService {

    public void execute() {
        System.out.println("I am another service.");
    }

}

 

    现在客户端只要这样写:

Java代码 复制代码  收藏代码
  1. public static void main(String[] args) {   
  2.     IService service = new AnotherService();           
  3.     IService proxy = ServiceFactory.getServiceProxy(service);           
  4.     proxy.execute();   
  5. }  
    public static void main(String[] args) {
        IService service = new AnotherService();        
        IService proxy = ServiceFactory.getServiceProxy(service);        
        proxy.execute();
    }

 

运行结果
Before print.
I am another service.
Before print.
 

    可以看到,不需要单独再为AnotherService写一个代理类了,动态代理类会帮助我们去实现的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值