代理模式

面试:你懂什么是分布式系统吗?Redis分布式锁都不会?>>>   hot3.png

简介
即Proxy Pattern,23种java常用设计模式之一。 代理模式的定义:给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。

代理模式的主要作用有两点:


1. 因为某些原因一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

Q: 何为“不想或者不能直接引用另一个对象”?

A: 如果执行某个操作需要进行远程调用网络另一端的计算机,如果不使用代理模式,则需要将复杂的网络通信部分硬编码入客户端。为了简化客户端的行为,可以使用代理模式,由客户端通过代理对象向远程的计算机发出指令,网络通信部分则有代理对象完成。

2. 在代理对象调用被代理对象的方法前后,可以附加一些额外的操作(如对数据加密)。

代理的种类

如果按照使用的目的类划分,代理有以下几种:

1:远程(remote)代理:为一个位于不同的地址空间的对象提供一个局域代表对象。这个不同的地址空间可以是本机器中,也可以是另外一台机器中.

2:虚拟(Virtual)代理:根据需要创建一个资源消耗较大的对象,使的此对象只在需要时才会本真正创建。例如,连接网络,加载图片等操作。

3:copy——on-write代理:虚拟代理的一种,把复制(克隆)拖延到只有在客户端需要时,才真正采取行动。

4:保护(Protect or access)代理:控制对某个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限。

5:智能引用(Smart Reference)代理:当一个对象被引用时,提供一些额外的操作,

还有一些其他的代理,这里不再一一列举。

代理的结构:

类图如下:


 

抽象主题(Subject)角色:申明了真正主题和代理主题的公共接口,这样在任何可以使用真正主题的地方使用代理主题

代理(Proxy)主题角色: 代理主题角色内部含有对真实主题的引用,从而可以在任何时候操作真正主题对象,代理主题角色提供一个与真正主题角色相同的接口,以便可以在任 何时候都可以代替真正主题,负责在需要的是他创建真正主题对象(和删除真正主题对象);代理角色通常在客户端调用传递给真实的主题之前或之后,都要执行某些操作,而不是单纯的将调用传递给真正的对象。

真正主题角色:定义了代理角色所代表的真正对象

在分析一下代理模式时序图

 

例如:

抽象接口

public abstract class Subject {
   abstract public void request();
}

真正主题角色:

public class RealSubject extends Subject {

    @Override
    public void request() {
        // TODO Auto-generated method stub
        System.out.println("from real subject");

    }

}

代理角色

public class ProxySubject extends Subject {
    private RealSubject realSubject;

    @Override
    public void request() {
        preRequest();
        if (realSubject == null) {
            realSubject = new RealSubject();
        }
        realSubject.request();
        postRequest();
    }

    private void preRequest() {
        System.out.println("=======preRequest()========");
    }

    private void postRequest() {
        System.out.println("=============postRequest()===========");
    }
}

测试类

public class Main {
  public static void main(String[] args) {
    ProxySubject proxy=new ProxySubject();
    proxy.request();
}
}

//

输出结果

=======preRequest()========
from real subject
=============postRequest()===========

二:动态代码

应用java中的反射机制,实现动态代理

下面是核心代理类


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

/***
 * 动态代理对象
 * 	
 * @author gavin
 *
 */
public class MyInvocationHandler  implements InvocationHandler {
    /**
     * 因为需要处理真实角色,所以要把真实角色传进来
     */
    Iinterface realSubject ;

    public MyInvocationHandler(Iinterface realSubject) {
        this.realSubject = realSubject;
    }

    /**
     *
     * @param proxy    代理类
     * @param method    正在调用的方法
     * @param args      方法的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("调用代理类");
        if(method.getName().equals("sellBooks")){
        	// 返回值是真实代理方法的返回值
            int invoke = (int)method.invoke(realSubject, args);
            System.out.println("调用的是卖书的方法");
            return invoke ;
        }else {
            String string = (String) method.invoke(realSubject,args) ;
            System.out.println("调用的是说话的方法");
            return  string ;
        }
    }
}

抽象接口


public interface Iinterface {
    public int sellBooks();

    public String speak();
}

真实代码


public class RealSubject  implements Iinterface{
    @Override
    public int sellBooks() {
        System.out.println("卖书---RealSubject ");
        return 1 ;
    }

    @Override
    public String speak() {
        System.out.println("说话----RealSubject");
        return "张三";
    }
}

测试类


public class Test {
	public static void main(String[] args) {
		test();
	}

	public static void test() {
		try {
			// 真实对象
			Iinterface realSubject = new RealSubject();
			MyInvocationHandler myInvocationHandler = new MyInvocationHandler(
					realSubject);
			// 代理对象
			Iinterface proxyClass = (Iinterface) Proxy.newProxyInstance(
					ClassLoader.getSystemClassLoader(),
					new Class[] { Iinterface.class }, myInvocationHandler);
			System.out.println("-------one---");
			proxyClass.sellBooks();
			System.out.println("-------two---");
			proxyClass.speak();
		} catch (Exception re) {
			String ss = re.getMessage();
			System.out.print(ss); // 真实对象

		}

	}
}

运行结果

-------one---
调用代理类
卖书
调用的是卖书的方法
-------two---
调用代理类
说话
调用的是说话的方法

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值