zoukankan      html  css  js  c++  java
  • 设计模式学习笔记:一、代理模式(动态代理步骤+举例)

    代理模式实现步骤:
           1.声明接口:注册需要被监听行为名称
           2.接口实现类: 扮演被监控的类,负责被监听方法实现细节
           3.InvocationHanler接口实现类:
                                        1.次要业务/增强业务
                                        2.将次要业务与被监听方法绑定执行
           4.代理监控对象:
                            被监控类内存地址,被监控类实现的接口,
                            InvocationHandler实现类的实例对象
     

    举例:

    饭前便后要洗手

    这里:主要业务是吃饭和上厕所,次要业务是洗手

    1.声明接口,声明主要业务是吃饭和上厕所

    public interface BaseService {
         public void eat();
         public void wc();
    }

    2.接口实现类,要实现吃饭和上厕所的实现类,这里拿person和dog做区分

    public class Dog implements BaseService {
    
    	@Override
    	public void eat() {
    	   System.out.println("啃骨头");
    	}
    
    	@Override
    	public void wc() {
    		 System.out.println("三腿立");
    
    	}
    
    }
    public class Person implements BaseService {
    
    	@Override
    	public void eat() {//主要业务,代理模式要求开发人员只关心主要业务
    	
            System.out.println("使用筷子吃饭....");
    	}
    
    	@Override
    	public void wc() {
    		   System.out.println("测试地球重力是否存在");
    
    	}
    
    }

    3.次要业务要实现InvocationHanler类,并重写invoke方法

    public class Invaction implements InvocationHandler {
    
    	    private BaseService    obj;//具体被监控对象
    	    
    	    public Invaction(BaseService param){
    	    	this.obj =param;
    	    }
    	
    	/*
    	 * 
    	 *  invoke方法:在被监控行为将要执行时,会被JVM拦截
    	 *             被监控行为和行为实现方会被作为参数输送invoke
    	 *             ****通知JVM,这个被拦截方法是如何与当前次要业务方法绑定实现 
    	 *  invoke方法三个参数
    	 *  
    	 *           int v= 小明.eat();//JVM拦截
    	 *            eat方法封装为Mehtod类型对象
    	 *            eat方法运行时接受所有的实参封装到Object[]
    	 *            将负责监控小明的代理对象作为invoke方法第一个参数
    	 * 
    	 */
    	@Override
    	public Object invoke(Object porxy, Method method, Object[] params) throws Throwable {
    		     //0.局部变量,接受主要业务方法执行完毕后返回值
    		     Object value;
    		    //1.确认当前被拦截行为
    		    String methodName= method.getName();
    		    //2.根据被拦截行为不同,决定主要业务和次要业务如何绑定执行
    		    if("eat".equals(methodName)){//饭前要洗手
    		    	wash();                            //洗手
    		    	value=method.invoke(this.obj, params);   //吃饭
    		    }else{//便后要洗手
    		    	value=method.invoke(this.obj, params);
    		    	wash();
    		    }
    		return value; //返回被拦截方法,需要调用地方
    	}
    	
    	//次要业务
    	public void wash(){
    		System.out.println("-----祈祷----");
    	}
    
    }

    4.创建代理监控对象:

    public class ProxyFactory {
    	/*
    	 * 
    	 *  JDK动态代理模式下,代理对象的数据类型
    	 *  应该由监控行为来描述 
    	 *  参数: Class文件,监控类
    	 */
    	public static  BaseService Builder(Class classFile)throws Exception {
    		
    		//1.创建被监控实例对象
    		 BaseService obj=  (BaseService) classFile.newInstance();
    		//2.创建一个通知对象
    		 InvocationHandler adviser= new Invaction(obj);
    		 //3.向JVM申请负责监控obj对象指定行为的监控对象(代理对象)
    		 /*
    		  *  loader:被监控对象隶属的类文件在内存中真实地址
    		  *  interfaces:被监控对象隶属的类文件实现接口
    		  *  h:监控对象发现小明要执行被监控行为,应该有哪一个通知对象进行辅助
    		  */
    		 BaseService $proxy= (BaseService) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), adviser);
    	     return $proxy;
    	}
    
    }

    测试:

    public static void main(String[] args) throws Exception {
    	   
    		//mike.eat();
    		//Person mike = new Person();
            BaseService dog= ProxyFactory.Builder(Dog.class);
            dog.eat();//专门负责监控mike的代理对象
            
            BaseService mike= ProxyFactory.Builder(Person.class);
            mike.eat();
           
    }

  • 相关阅读:
    Unique Paths II
    Subsets II
    Subsets
    Jump Game II
    Jump Game
    Valid Sudoku
    Valid Parentheses
    Length of Last Word
    Trapping Rain Water
    Sum Root to Leaf Numbers
  • 原文地址:https://www.cnblogs.com/dulinan/p/12033034.html
Copyright © 2011-2022 走看看