您的位置:首页 > 其它

代理设计模式--Proxy

2015-03-29 11:14 232 查看
代理模式(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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: