您的位置:首页 > 编程语言 > Java开发

代理模式(静态代理、jdk动态代理)

2016-09-27 17:56 615 查看
1.代理模式的定义:

为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

2.组成的角色:
抽象角色:通过接口或抽象类声明真实角色实现的业务方法。
代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。

3.代理模式的好处:

(1).职责清晰
真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。
(2).代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了中介解耦的作用和保护了目标对象的作用,并可以附加自己的操作。
(3).高扩展性

4.通过小例子理解代理模式:

public abstract class AbstractTarget {

public abstract void dosomething();
}

public class ConcreteTarget extends AbstractTarget {
@Override
public void dosomething() {
System.out.println("go home");
}
}

public class MyProxy extends AbstractTarget {
//静态代理
//编译期就已经明确指定了真实需要代理的类就是ConcreteTarget
private AbstractTarget target = new ConcreteTarget();

@Override
public void dosomething() {
target.dosomething();
}
}

public static void main(String[] args) {
AbstractTarget target = new MyProxy();
target.dosomething();
}

执行结果:

go home

这是一个最简单到代理模式的例子,客户端使用代理的dosomething()方法时,代理类委托给了真实角色ConcreteTarget执行,这就是代理模式。代理类成为客户端与真实角色直接的桥梁,在不同的场景下,这个桥梁可以起到很大的现实作用,这个在本文后面再讲述。

可以看到,该例中由于编译期已经知道代理的真实角色是谁了,所以这种代理模式又叫做静态代理

//静态代理
//编译期就已经明确指定了真实需要代理的类就是ConcreteTarget
private AbstractTarget target = new ConcreteTarget();


5.jdk动态代理

相对静态代理而言,动态代理是值编译器不知道代理的真实角色是谁,需要在运行期才能确定。

我们有一个超级明星的接口。

public interface SuperStar {

void call();

void sing();

void dance();
}


有一个歌手实现了超级明星的接口。

public class Singer implements SuperStar {

@Override
public void call() {
System.out.println("我正在休息,不要打扰我");
}

@Override
public void sing() {
System.out.println("唱歌我在行,让我来");
}

@Override
public void dance() {
System.out.println("跳舞找dancer去");
}
}

但是明星都很忙的,还要耍耍大牌,所以需要一个经纪人作为他的代理人,处理对外事宜。可是现在是用的jdk动态代理了,与先前的例子写法完全不一样了。jdk API中有个InvocationHandler调用处理器的接口。我们需要先定义一个自己的调用处理器。

public class BrokerInvocationHandler implements InvocationHandler {

private SuperStar superStar;

public BrokerInvocationHandler(SuperStar superStar){
this.superStar = superStar;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("sing")){
method.invoke(superStar,args);
System.out.println("歌手同意了,我们准备准备就来");
return null;
}else if (method.getName().equals("dance")){
System.out.println("跳舞别来找我们");
return null;
}else if (method.getName().equals("call")){
System.out.println("人不在,有什么事找我好了");
return null;
}else {
return null;
}
}
}

public class BrokerProxy {

public static SuperStar newProxyInstance(SuperStar superStar){
return (SuperStar) Proxy.newProxyInstance(superStar.getClass().getClassLoader(),
superStar.getClass().getInterfaces(),new BrokerInvocationHandler(superStar) );
}
}

有了这2个类,代理就算完成了。

public class Test {

public static void main(String[] args) {
SuperStar singer = BrokerProxy.newProxyInstance(new Singer());
singer.sing();
singer.call();
singer.dance();
//true:说明singer的父类就是Proxy
System.out.println(singer.getClass().getSuperclass() == Proxy.class); }}

运行结果:

唱歌我在行,让我来

歌手同意了,我们准备准备就来

人不在,有什么事找我好了

跳舞别来找我们

true

jdk动态代理总结:

     

      1.定义自己的InvocationHandler实现类BrokerInvocationHandler

     

      2.通过Proxy类的newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)方法创建动态代理类

     

      3.通过反射获取动态代理类的构造函数,并通过该构造函数创建代理类实例singer

     

      4.被创建出来的实例singer继承了Proxy类(因此java动态代理只能代理接口,这是由java不支持多继承的设计决定的),实现了目标接口SuperStar

     

      5.调用singer的任意方法,实际上都会先调用到BrokerInvocationHandler中的invoke方法,然后通过反射调用Method的invode方法调用实际被代理的方法

     

      6.调用到BrokerInvocationHandler中的invoke方法时,可以获得被代理方法的信息,因此可以在真正调用invoke方法前、后写上自己的业务逻辑

5.代理模式的变形

在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用 Proxy模式。下面是一些可以使用Proxy模式常见情况:
1) 远程代理(Remote  Proxy)为一个位于不同的地址空间的对象提供一个本地的代理对象。这个不同的地址空间可以是在同一台主机中,也可是在另一台主机中,远程代理又叫做大使(Ambassador)

2) 虚拟代理(Virtual Proxy)根据需要创建开销很大的对象。如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。 

3) 保护代理(Protection Proxy)控制对原始对象的访问。保护代理用于对象应该有不同的访问权限的时候。

4) 智能指引(Smart Reference)取代了简单的指针,它在访问对象时执行一些附加操作。

5) Copy-on-Write代理:它是虚拟代理的一种,把复制(克隆)操作延迟到只有在客户端真正需要时才执行。一般来说,对象的深克隆是一个开销较大的操作,Copy-on-Write代理可以让这个操作延迟,只有对象被用到的时候才被克隆。

6)缓存代理(Cache Proxy)

7)防火墙代理(Application Gateway)

8)同步代理

等等。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息