代理设计模式--Proxy

              代理模式(Proxy):为其他对象提供一种代理以控制这个对象的访问。

              代理模式类别:

                      1.远程代理:为一个对象在不同的地址空间提供局部代理,这样可以隐藏一个对象存在于不同地址空间的事实。比如:使用nexus构建私服就相当于是使用远程代

              理的方式,使得工程依赖的jar包不要一直去远程访问。

                      2.虚拟代理:根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象。这样就可以在一定的程度上提升系统的性能。

                      3.安全代理:用来控制真实对象访问时的权限。一般用于对象应该有不同的访问权限的时候。

                      4.智能指引:是指当调用真实对象时,代理处理另外的一些事情。如:计算真实对象的引用次数,这样当该对象没有引用是,可以自动释放它;或当第一次引用一

             个持久对象时,将它装入内存;或在访问一个实际对象前,检查是否已经锁定它,以确保其他对象不能改变它,这些都是通过代理在访问一个对象时附加一些内部的处  

             理。

                      总之,代理模式其实就是在访问对象时插入一定程度的间接性处理,因为这种机制可以附加多种用途。

            

            上面讲解都是理论上的东西,下面结合代码来分析一下代理模式中的两种代理模式:静态代理和动态代理

             代理模式一般涉及到三个角色:

                     1.抽象角色:声明真实角色的接口

                     2.真实角色:抽象角色的实现

                     3.代理角色:代理角色内可以含有真实角色的引用,同时可以实现一些附加操作

             一、静态代理

                      静态代理:静态代理中就是简单的将真实角色中的方法重新实现,重载抽象类中声明的方法。

                      静态代理的缺点是代理与真实角色一一对应,所以对于每一个要被代理的类,都要有一个代理类与之对应,并且都要实现抽象角色中的所有方法。所以这样代码的

                  复用率就下降了。

                      下面就贴出代码:

            A.抽象角色:

package com.jjyy.jdbc.inter;

/**
 * 电话的接口
 * 
 * @author JiangYu 2015年3月29日
 *
 */
public interface Phone {
	/**
	 * call 方法
	 */
	public void call();
	/**
	 * sendMsg 方法
	 */
	public void sendMsg();
}

          B.代理角色

package com.jjyy.jdbc.decoration;

import com.jjyy.jdbc.inter.Phone;
/**
 * 静态代理模式---前提是对象已经存在了
 * @author JiangYu
 * 2015年3月29日
 *
 */
public class DecorateSamsungPhone implements Phone{
	
	private Phone phone = null;
	//通过构造方法传递对象
	public DecorateSamsungPhone(Phone phone) {
		this.phone = phone;
	}
	@Override
	public void call() {
		phone.call();
	}

	@Override
	public void sendMsg() {
		System.out.println("SamsungPhone sendMsg:Hello Samsung");
	}

}

            C.真实对象

package com.jjyy.jdbc.decoration;

import com.jjyy.jdbc.inter.Phone;

/**
 * 静态代理设计模式
 * 真实类要和代理类要实现相同的接口
 * 在代理类的构造方法中传入被代理类的对象,这样就可以使用被代理对象的方法进行不同的装饰
 * @author JiangYu
 * 2015年3月29日
 *
 */
public class SamsungPhone implements Phone {

	@Override
	public void call() {
		System.out.println("SumsungPhone call...");
	}

	@Override
	public void sendMsg() {
		System.out.println("Phone sendMsg...");
	}
	
}


            D.测试类:

package com.jjyy.jdbc.decoration;

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

import org.junit.Test;

import com.jjyy.jdbc.dynamicProxy.DynamicProxyIPhone;
import com.jjyy.jdbc.inter.Phone;
/**
 * 静态代理模式和动态代理设计模式
 * @author JiangYu
 * 2015年3月29日
 *
 */
public class DesignModel {
	/**
	 * 静态代理设计模式
	 */
	@Test
	public void decorationDesignTest(){
		//被装饰类
		SamsungPhone phone = new SamsungPhone();
		//装饰类
		DecorateSamsungPhone samsungPhone = new DecorateSamsungPhone(phone);
		//调用装饰之后的对象的方法
		samsungPhone.call();
		samsungPhone.sendMsg();
	}
	
}

             

                 二、动态代理

                         动态代理:为了解决静态代理的问题----代码的复用率低。动态代理一般要满足代理的三个角色,然后还要实现一个接口---InvocationHandler,该接口中有一 

               个invoke方法。

                         理论的知识有点抽象,贴出代码:

                A.真实角色

package com.jjyy.jdbc.decoration;

import com.jjyy.jdbc.inter.Phone;
/**
 * 动态代理:真实角色
 * @author JiangYu
 * 2015年3月29日
 *
 */
public class IPhone implements Phone{

	@Override
	public void call() {
		System.out.println("IPhone call...");
	}

	@Override
	public void sendMsg() {
		System.out.println("IPhone sendMsg...");
	}

}

                 B.代理角色

package com.jjyy.jdbc.dynamicProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
 * 动态代理类--代理类
 * @author JiangYu
 * 2015年3月29日
 *
 */
public class DynamicProxyIPhone implements InvocationHandler {
	
	private Object obj = null;
	
	public Object registerObj(Object obj){
		this.obj = obj;
		//所有的接口都绑定到了代理类对象上,保证真实对象和代理对象有着共同的行为
		return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		System.out.println("dynamic Proxy...");
		//代理对象处理特殊的方法
		if ("sendMsg".endsWith(method.getName())) {
			System.out.println("IPhone sendMsg:Hello IPhone From DynamicProxy...");
			return null;
		}else {
			return method.invoke(this.obj, args);
		}
	}
}

                  C.测试类

package com.jjyy.jdbc.decoration;

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

import org.junit.Test;

import com.jjyy.jdbc.dynamicProxy.DynamicProxyIPhone;
import com.jjyy.jdbc.inter.Phone;
/**
 * 静态代理模式和动态代理设计模式
 * @author JiangYu
 * 2015年3月29日
 *
 */
public class DesignModel {
	
	/**
	 * 动态代理设计模式--实现方式之二
	 * 1.真实类和代理类具有相同的行为
	 * 2.代理类要实现InvocationHandler接口,事项invoke方法
	 * 3.代理类可以对真实类的行为进行增强
	 * 4.调用代理类对象的方法
	 */
	@Test
	public void dynamicProxyDesignTest(){
		//真实类
		IPhone phone = new IPhone();
		//代理类
		DynamicProxyIPhone proxy = new DynamicProxyIPhone();
		//代理对象
		IPhone proxyPhone = (IPhone) proxy.registerObj(phone);
		//调用代理对象的方法
		proxyPhone.call();
		proxyPhone.sendMsg();
	}
}

                 上面的动态代理方式是一种常规的方式,另外还有一种方式是比较常用的动态代理写法--在测试类中直接用内部类来实现InvocationHandler

package com.jjyy.jdbc.decoration;

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

import org.junit.Test;

import com.jjyy.jdbc.dynamicProxy.DynamicProxyIPhone;
import com.jjyy.jdbc.inter.Phone;
/**
 * 静态代理模式和动态代理设计模式
 * @author JiangYu
 * 2015年3月29日
 *
 */
public class DesignModel {
	
	/**
	 * 动态代理设计模式--实现方式之一
	 */
	@Test
	public void proxyDesignTest(){
		final IPhone iPhone = new IPhone();
		//动态代理
		Phone proxy = (Phone) Proxy.newProxyInstance(IPhone.class.getClassLoader(), IPhone.class.getInterfaces(), new InvocationHandler() {
			
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				if("sendMsg".equals(method.getName())){//如果是sendMsg时,就进行特殊的处理
					System.out.println("Iphone sendMsg:Hello IPhone");
					return null;
				}else {//其他的方法还是按照原来的方法进行
					return method.invoke(iPhone, args);
				}
			}
		});
		//通过代理对象去执行响应的方法
		proxy.call();
		proxy.sendMsg();
	}
	
}


                以上的动态代理是jdk的proxy,其实它也不是完美的,它只能代理实现了接口的类,不能对类本身实现代理,如果要完成对类本身实现代理,需要用到一个开源的

         cglib。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值