Java设计模式——代理设计模式

目录

  • 定义
  • 静态代理模式
  • 动态代理模式

定义

生活中:
(1)自己不方便做一些事情,例如:去国外 找代购
(2)自己没资源,例如:找女朋友 找红娘

Java中:
当前这个类做一些事情,不太方便,因为这个事情是多变,重复的,就可以交给代理。

例如:项目经理说,在测试环境,即开发阶段(不是生产环境,上线就是生产环境),测试一下每一个方法的运行时间,并且记录方法运行的日志。 开发完之后,项目经理又要求把那些测试代码都去掉。那么我么需要挨个删除或者注释。工作量就会很大。

interface DAO{
     
	void add();
}
class UserDAOImpl implements DAO{
     

	@Override
	public void add() {
     
//		System.out.println("add方法开始执行");
//		long start = System.currentTimeMillis();
	
	System.out.println("添加用户");//只有这行代码是核心代码,其他都是测试代码,用完就要去除。
		
//		long end = System.currentTimeMillis();
//		System.out.println("运行时间:" + (end-start));
//		System.out.println("add方法执行结束");
	}	
}

为了解决这个问题,就需要采用代理设计模式进行代码优化。

静态代理模式

要求代理类与被代理类实现同一个接口,且代理者必须持有被代理者的引用

public class TestAgent {
     
    @Test
    public void test02(){
     
        //new GoodsDAOImpl()被代理者对象
        //new DAOProxy(x)代理者对象
        DAO d = new DAOProxy(new GoodsDAOImpl());
        d.add();
    }

    @Test
    public void test01(){
     
        //new UserDAOImpl()被代理者对象
        //new DAOProxy(x)代理者对象
        DAO d = new DAOProxy(new UserDAOImpl());
        d.add();
    }

    public static void main(String[] args) {
     
        GoodsDAOImpl dao = new GoodsDAOImpl();
        dao.add();//因为有代理类实现测试要求,并不会修改核心类的代码。
    }
}

interface DAO{
     //
    void add();
}
class UserDAOImpl implements DAO{
     
    @Override
    public void add() {
     
        System.out.println("添加用户");
    }
}
class GoodsDAOImpl implements DAO{
     
    @Override
    public void add() {
     
        System.out.println("添加商品");
    }
}

class DAOProxy implements DAO{
     //代理类
    private DAO dao;//持有被代理者的引用,因为核心业务逻辑仍然交给被代理者自己完成

    //之所以要求代理类与被代理类实现同一个接口,是为了让一个构造函数就满足被代理者的引用,否则要重载多个构造函数
    public DAOProxy(DAO dao) {
     
        super();
        this.dao = dao;
    }

    @Override
    public void add(){
     
        System.out.println("add方法开始执行");
        long start = System.currentTimeMillis();
        dao.add();//核心业务逻辑交给被代理者自己
        long end = System.currentTimeMillis();
        System.out.println("运行时间:" + (end-start));
        System.out.println("add方法执行结束");
    }
}

缺点:一个代理类只能替一个代理主题(接口)代理工作
如果要解决此问题需要动态代理模式。

动态代理模式

优点:一个代理工作处理器,可以替多个代理主题代理工作,只有代理工作内容一样就可以。

要求步骤:
(1)编写一个代理工作处理器的类,这个类必须实现一个接口InvocationHandler

(2)用JDK中提供了一个Proxy类,来创建代理类的对象
new ProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)
参数一:被代理者的类加载器对象
参数二:被代理者实现的接口们
参数三:代理者替被代理者要完成的工作的处理器对象
(3)调用方法

代码演示:

public class TestProxy {
     
    @Test
    public void test01() {
     
        AImpl a = new AImpl();//被代理者

        ClassLoader loader = a.getClass().getClassLoader();//被代理者的类加载器对象
        Class<?>[] interfaces = a.getClass().getInterfaces();//被代理者实现的接口们
        Handler h = new Handler(a);//代理者替被代理者要完成的工作的处理器对象

        //实现A主题接口
        A proxy = (A) Proxy.newProxyInstance(loader, interfaces, h);
        proxy.a();
        /*a方法开始执行
          a方法被执行
          运行时间:0
          a方法执行结束*/
    }

    @Test
    public void test02() {
     
        BImpl b = new BImpl();//被代理者

        ClassLoader loader = b.getClass().getClassLoader();
        Class<?>[] interfaces = b.getClass().getInterfaces();
        Handler h = new Handler(b);

        //实现B主题接口
        B proxy = (B) Proxy.newProxyInstance(loader, interfaces, h);
        proxy.b();
        /*b方法开始执行
          b方法被执行
          运行时间:0
          b方法执行结束*/

    }
}
class Handler implements InvocationHandler {
     
    private Object target;//被代理者对象

    public Handler(Object target) {
     
        super();
        this.target = target;
    }

    /*
     * 参数一:代理类的对象
     * 参数二:被代理者要执行的方法
     * 参数三:被代理者要执行的方法需要的实参列表
     * 这个方法不是程序调用的,是一会执行代理类对象的方法时自动调用
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
     
        System.out.println(method.getName() + "方法开始执行");
        long start = System.currentTimeMillis();

       //method.invoke(obj, args);//obj是要求写被代理者对象
        Object value = method.invoke(target, args);

        long end = System.currentTimeMillis();
        System.out.println("运行时间:" + (end-start));
        System.out.println(method.getName() + "方法执行结束");

        return value;
    }
}

//主题1
interface A{
     
    void a();
}
//被代理者1
class AImpl implements A{
     
    @Override
    public void a() {
     
        System.out.println("a方法被执行");
    }
}
//主题2
interface B{
     
    void b();
}
//被代理者2
class BImpl implements B{
     
    @Override
    public void b() {
     
        System.out.println("b方法被执行");
    }
}

你可能感兴趣的:(设计模式,java)