`
he_wen
  • 浏览: 241461 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

代理模式

阅读更多

 一、模式的提出

  为其他对象提供一种代理以控制对这个对象的访问。其实,observer也是一种代理模式

二、业务背景

  要测试一个方法运行了多长时间怎么测试?要给一个方法记录日志文件怎么记录?怎样动态的设置该方法(是先记录日志文件、还是先测试运行该方法多长时间)的先后顺序,本文以测试坦克方法为例

三、UML图


四、代码详解

测试方法的接口

package com.hewen.proxy;

public interface Moveable {
	  public void move();//测试运行方法
}

 
Tank类

package com.hewen.proxy;
import java.util.Random;
public class Tank implements Moveable{

	public void move() {
	System.out.println("Tank moving....");
	try {
		Thread.sleep(new Random().nextInt(10000));//休眠
	} catch (InterruptedException e) {
		e.printStackTrace();
	}
	
	}
}

时间记录类

package com.hewen.proxy;

public class TankTimeProxy implements Moveable {
	private Moveable t;//只要类实现了该接口,就可以动态代理这个方法
	public TankTimeProxy(Moveable t) {
		this.t=t;
	}
	public void move() {
		long start=System.currentTimeMillis();
		t.move();
		long end=System.currentTimeMillis();
		System.out.println("time:"+(end-start));

	}

}

日志记录类

package com.hewen.proxy;

public class TankLogProxy implements Moveable {

	private Moveable t;//代理对象
	public TankLogProxy(Moveable t) {
		this.t=t;
	}
//可以为这个方法设置日志
	public void move() {
		System.out.println("tank start......");
		t.move();
		System.out.println("tank stop......");
	}
}

 主方法测试类

package com.hewen.proxy;

public class Test {
public static void main(String[] args){
	//测试坦克运行的方法的时间,以及该方法的日志管理
	//Moveable t=new TankLogProxy(new TankTimeProxy(new Tank()));
	//t.move();
	
	Moveable t=new TankTimeProxy(new TankLogProxy(new Tank()));
	t.move();
}
}

运行的结果

tank start......
Tank moving....
tank stop......
time:7328

时序图:

 

还有一个是java虚拟机代理动态调用     

 业务背景:有一个疑问希望网友解释的越详细越好,

自己查看源码proxy类是怎样动态的调用invoke方法?

这是一个代理类

package com.cn.dynamic.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
 * 代理类实现了InvocationHandler接口,
 * 通过其中一个代理接口的代理实例上的方法调用将被指派到实例的调用处理程序的 Invoke 方法,
 * 并传递代理实例、识别调用方法的 java.lang.reflect.Method 对象以及包含参数的 
 * Object 类型的数组。调用处理程序以适当的方式处理编码的方法调用,
 * 并且它返回的结果将作为代理实例上方法调用的结果返回。 

 * @author Administrator
 *
 */
public class DynamicProxySay implements InvocationHandler {

	private Object proxyOperation; // 操作者对象   
    private Object proxyLogic; // 业务逻辑对象   

  
    /**  
     * 获得代理对象(业务逻辑)  
     *   
     * @param proxyOperation  
     * @param proxyLogic  
     * @return  
     */  
    public Object getProxyObj(Object proxyOperation, Object proxyLogic) {   
        this.proxyOperation = proxyOperation;   
        this.proxyLogic = proxyLogic;  
        /**两种方式调用
         * 第一种方式:这个是比较复杂的返回代理的实例对象,
         * 返回代理类的 java.lang.Class 对象,注意一定是要
         */
          Class proxyClass = Proxy.getProxyClass(
                this.proxyLogic.getClass().getClassLoader(), 
                 this.proxyLogic.getClass().getInterfaces() );
          try {//得到构造方法新建一个代理对象
			return    proxyClass.getConstructor(new Class[] { InvocationHandler.class }).
			        newInstance(new Object[] { this });
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}
		return proxyClass;
		//第二种方式: 比较简易的返回一个代理实例对象, 
      /*  return Proxy.newProxyInstance(this.proxyLogic.getClass()   
                .getClassLoader(), this.proxyLogic.getClass().getInterfaces(),   
                this);   */
    }   
  
    /**  
     * JVM动态调用  
     */  
    public Object invoke(Object proxy, Method method, Object[] args)   
            throws Throwable {   
    	/**
    	 * 判断是否是代理类
    	 */
//    	if(Proxy.isProxyClass(Proxy.getProxyClass(this.proxyLogic.getClass()   
//                .getClassLoader(), this.proxyLogic.getClass().getInterfaces()))){
//    		System.out.println("this dynamic proxy class!");
//    	}
        Object resultObj = null;   
  
        try {   
            Class operCls = this.proxyOperation.getClass();
            //得到操作类的方法,参数是start名字和该方法的参数
            Method start = operCls.getMethod("start",   
                    new Class[] { Method.class });   
            // 反射执行start方法,参数是该方法的对象和该方法的参数   
            start.invoke(proxyOperation, new Object[] { method });   
  
            // 执行业务逻辑对象   
            resultObj = method.invoke(proxyLogic, args);   
  
            Method end = operCls.getMethod("end", new Class[] { Method.class });   
            // 反射执行end方法   
            end.invoke(proxyOperation, new Object[] { method });   
  
        } catch (Exception e) {   
            e.printStackTrace();   
        }   
  
        return resultObj;   
    }   


}

 客户端的调用

package com.cn.dynamic.proxy;

import com.cn.dynamic.operator.ISay;
import com.cn.dynamic.operator.Say;
/**
 * 测试方法
 * @author Administrator
 *
 */
public class Client {
	 public static void main(String[] args) {   
		    //对业务逻辑做日志的操作方法
	        IOperatorExecutor operExe = new LoggerOperation();
	        //业务逻辑方法
	        ISay say = new Say();  
	        //返回代理对象
	        ISay proxySay = (ISay) new DynamicProxySay().getProxyObj(operExe, say);   
	        proxySay.sayHello("Alice"); //代理对象动态的调用invoke方法  
	        System.out.println();   
	        proxySay.sayGoodBye("Bob");   //代理对象动态的调用invoke方法
	    }   

}

 业务逻辑的接口 

package com.cn.dynamic.operator;

public interface ISay {
	 void sayHello(String name);   
	 void sayGoodBye(String name);   
}

 实现业务逻辑的类

package com.cn.dynamic.operator;

public class Say implements ISay{

	public void sayGoodBye(String name) {
		System.out.println("goodBye: "+name);
		
	}

	public void sayHello(String name) {
		System.out.println("hello: "+name);
	}

}

记录日志的接口

package com.cn.dynamic.proxy;

import java.lang.reflect.Method;


public interface IOperatorExecutor {
	void start(Method method);   
	  
    /**  
     * 方法执行之前的操作  
     *   
     * @param method  
     */  
    void end(Method method);  
}

 实现记录日志的类

package com.cn.dynamic.proxy;

import java.lang.reflect.Method;

import com.cn.dynamic.Level;
import com.cn.dynamic.Logger;

public class LoggerOperation implements IOperatorExecutor {

	public void end(Method method) {
		 Logger.log(Level.INFO, method.getName() + " method end...");   

	}

	public void start(Method method) {
		 Logger.log(Level.INFO, method.getName() + " method start...");   

	}

}

 记录日志类依赖的类

package com.cn.dynamic;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class Logger {
/*
 * 重做方法日志
 */
		public static void log(Level level, String logInfo) {
			if (level.equals(Level.INFO)) {
				System.out.println("Logger INFO : "
						+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
								.format(new Date()) + " " + logInfo);
			} else if (level.equals(Level.WARN)) {
				System.out.println("Logger WARN : "
						+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
								.format(new Date()) + " " + logInfo);
			} else if (level.equals(Level.DEBUG)) {
				System.out.println("Logger DEBUG : "
						+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
								.format(new Date()) + " " + logInfo);
			}

     }
}

 

package com.cn.dynamic;

public enum Level {
	INFO,WARN,DEBUG; 
}

 运行的结果

Logger INFO : 2010-09-04 18:23:41 sayHello method start...
hello: Alice
Logger INFO : 2010-09-04 18:23:41 sayHello method end...

Logger INFO : 2010-09-04 18:23:41 sayGoodBye method start...
goodBye: Bob
Logger INFO : 2010-09-04 18:23:41 sayGoodBye method end...

 

  • 大小: 9.4 KB
  • 大小: 14.3 KB
0
1
分享到:
评论
1 楼 shmily2038 2010-09-04  
这个只能算是静态的代理。你没有使用到Proxy代理类,来进行动态代理。

相关推荐

    代理模式的使用示例程序

    代理模式是一种设计模式,它在软件工程中扮演着重要的角色,允许我们为其他对象提供一个替代接口,以控制对原始对象的访问。这种模式的主要目的是为了增加灵活性、安全性或者在不修改原有对象的情况下,增强或扩展其...

    JAVA设计模式之代理模式实例

    代理模式是设计模式的一种,它提供了一种对目标对象进行增强或者控制访问的方式。在本实例中,我们将深入探讨Java中的代理模式及其应用。 代理模式的核心思想是为一个对象创建一个代理对象,这个代理对象在客户端和...

    设计模式之代理模式Proxy

    代理模式是设计模式中的一种结构型模式,它在对象交互中起到了中介的作用,允许通过代理对象来控制对原对象的访问。代理模式的核心思想是为一个对象提供一个替身,以便增加新的功能或者控制对原对象的访问。这种模式...

    Android设计模式之代理模式(Proxy Pattern)

    代理模式是设计模式的一种,它的主要目的是在不改变原有对象的基础上,为一个对象提供额外的功能或者控制对这个对象的访问。在Android开发中,代理模式的应用尤为常见,尤其在处理复杂的业务逻辑、网络请求、界面...

    android使用signalr代理模式和非代理模式

    SignalR提供了两种主要的工作模式:代理模式和非代理模式。这两种模式在实现上有所不同,各自具有优缺点,适用于不同的场景。 **1. 代理模式(Proxy Mode)** 在代理模式下,SignalR为每个Hub(服务端的业务逻辑...

    设计模式-代理模式

    代理模式是一种常用的设计模式,它在软件开发中扮演着重要的角色,特别是在iOS平台的应用程序设计中。代理模式的核心思想是为一个对象提供一个替身或代理,以控制对这个对象的访问。这种模式允许我们通过代理来间接...

    java中的三种代理模式

    在Java编程中,代理模式是一种常用的面向对象设计模式,它允许我们为一个对象提供一个代理以控制对该对象的访问。代理模式通常用于增加额外的功能,如日志、权限检查等,或者为了创建虚拟代理以提高性能。以下是Java...

    JAVA设计模式(代理模式)

    **Java设计模式——代理模式详解** 代理模式是软件设计模式中的一个重要组成部分,它在Java编程中扮演着举足轻重的角色。代理模式的核心思想是为一个对象提供一个替身,这个替身即代理对象,代理对象可以控制对原...

    代理模式小例子

    代理模式是一种设计模式,它在软件工程中扮演着重要的角色,允许我们为其他对象提供一个替代接口,以控制对原对象的访问。这种模式的主要目的是为了增加灵活性、安全性或者为对象提供额外的功能,同时保持客户端代码...

    设计模式之代理模式proxy

    **设计模式之代理模式(Proxy Pattern)** 设计模式是软件工程中的一种最佳实践,它是在特定情境下解决常见问题的模板。代理模式是其中一种行为设计模式,它的核心思想是为一个对象提供一个替身或者代理,以控制对...

    设计模式实现——代理模式

    **设计模式实现——代理模式** 在软件工程中,设计模式是一种通用可重用的解决方案,它描述了在特定上下文中经常出现的问题以及该问题的解决方案。代理模式是设计模式的一种,它提供了一种对目标对象的间接访问方式...

    结构型模式之代理模式(Proxy)

    代理模式是一种设计模式,属于结构型模式之一,其主要目的是为其他对象提供一个代理,以控制对该对象的访问。在实际应用中,代理模式能够帮助我们实现如下的功能: 1. 远程代理:代理对象可以代表一个位于远程系统...

    Java设计模式-代理模式例子

    在这个“Java设计模式-代理模式例子”中,我们将深入探讨代理模式的概念、实现方式以及它在实际开发中的应用。 代理模式的核心思想是为一个对象提供一个替身,这个替身即代理对象,代理对象控制对原对象的访问。在...

    android设计模式之代理模式

    代理模式在软件设计中是一种常用的设计模式,尤其在Android开发中,它可以帮助我们实现复杂的控制逻辑,隔离复杂性,以及提供额外的功能。在Android上下文中,代理模式常常用于数据加载、权限控制、事件处理等方面。...

    设计模式C++学习之代理模式(Proxy)

    代理模式是一种设计模式,它是结构型模式之一,主要用于在客户端和目标对象之间建立一个代理对象,以便控制对目标对象的访问。在C++中,代理模式可以用来为其他对象提供一种代理以控制对这个对象的访问,或者增加...

    Java代理模式Java动态代理

    ### Java代理模式与Java动态代理详解 #### 一、代理模式概述 代理模式是一种软件设计模式,它在客户端和目标对象之间提供了一种间接层。这种模式的主要目的是控制客户端对目标对象的访问,并且可以在不修改原有...

    设计模式--代理模式

    代理模式是一种常用的设计模式,它在软件开发中扮演着重要角色,允许我们通过一个代理类来控制对原对象的访问。在《设计模式:可复用面向对象软件的基础》(通常称为GoF设计模式)中,代理模式被定义为“为其他对象...

    代理模式 C++实现

    代理模式(Proxy) 定义: 为其他对象提供一种代理以控制对这个对象的访问 结构: 由三部分组成 1.RealSubject(真实对象): 真正会调用到的对象 2.Proxy(代理对象): 代理真实对象的地方 3.Subject(共同点): 代理对象...

    cas代理模式代码示例

    在IT行业中,代理模式是一种常见的设计模式,它允许我们在不修改原有对象的基础上,为对象添加新的功能或控制访问。在本示例中,我们将重点讨论如何在Java环境下使用代理模式来实现代理逻辑,特别是在CAS(Central ...

Global site tag (gtag.js) - Google Analytics