设计模式之代理模式

本文详细介绍了代理模式的概念、作用及应用场景。通过远程代理、虚拟代理、缓存代理、保护代理等多个实例,阐述了代理模式如何控制对象访问,包括在Java RMI中的应用。同时,提到了静态代理和动态代理的区别,以及正向代理和反向代理在负载均衡中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概述

  代理模式为一个对象提供一个替身以控制对这个对象的访问。其实代理就是做到类似转发的功能,针对不同代理,转发的具体实现不同。

二、解决问题

  从原理知道他就是控制客户对一个对象的访问,它跟现实中的中介代理类似,只是作为代表做一些受理工作,真正执行的并不是它自己。比如买火车票,外面有很多火车票代理点,我们直接去代理点买票就好而不用跑到火车票买了(暂时不考虑网购哈)。

三、结构类图

 

四、应用实例

  在这个例子中,主要讲解远程代理,它可以作为另一个JVM上的本地代表。客户端调用代理的方法,代理会利用网络把请求转发到远程执行,并把执行结果通过网络返回到代理,最终返回到客户端。

  下面使用引用java RMI(Remote Method Invoke远程方法调用)的例子讲解远程代理模式。它的的工作原理图如下,用户向服务器A发起话费充值请求,服务器A通过网络调用服务器B的方法,服务器B把充值结果返回到服务器A,最后返回到用户。

 

代码实现如下,首先创建一个远程接口

复制代码
package com.jet.pattern.proxy;

import java.net.MalformedURLException;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;

/**
 * description:
 * 远程接口,其继承java的Remote接口,真正干活对象和代理都要实现这个接口
 * Created by Administrator on 2017/1/17.
 */
public interface MyRemote extends Remote{
    // 远程调用有风险告诉客户端
    public String request(int money) throws RemoteException, MalformedURLException, NotBoundException;
}
复制代码

创建远程对象

复制代码
package com.jet.pattern.proxy.impl;

import com.jet.pattern.proxy.MyRemote;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;

/**
 * description:
 * 真正干活的对象,接受代理对象的访问
 * Created by Administrator on 2017/1/17.
 */
// 继承UnicastRemoteObject,让jvm帮我们完成远程调用
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote{
    // 父类构造器抛出了异常,所以子类构造器也需要抛出异常
    public MyRemoteImpl() throws RemoteException {
    }

    @Override
    public String request(int money) throws RemoteException {
        System.out.println("充值" + money + "元话费成功");
        return "充值成功";
    }

    public static void main(String[] args) {
        try {
            // 产生远程对象
            MyRemote service = new MyRemoteImpl();

            // 注册远程访问接口
            LocateRegistry.createRegistry(8888);

            // 注册远程对象,注册名为RemoteHello,代理访问时指定这个名称就可以找到本类,
            Naming.rebind("rmi://localhost:8888/RemoteHello",service);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
复制代码

创建代理对象

复制代码
package com.jet.pattern.proxy.impl;

import com.jet.pattern.proxy.MyRemote;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

/**
 * description:
 * 代理对象,控制客户端的访问,把客户端访问请求转发到真正干活的对象
 * Created by chenzanjin on 2017/2/4.
 */
public class Proxy implements MyRemote {
    @Override
    public String request(int money) throws RemoteException, MalformedURLException, NotBoundException {
        MyRemote remote = (MyRemote)Naming.lookup("rmi://localhost:8888/RemoteHello");
        return remote.request(money);
    }
}
复制代码

创建访问客户端

复制代码
package com.jet.pattern.proxy.test;

import com.jet.pattern.proxy.MyRemote;
import com.jet.pattern.proxy.impl.Proxy;
import java.net.MalformedURLException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

/**
 * description:
 * 代理客户端,测试对代理的访问
 * Created by chenzanjin on 2017/2/4.
 */
public class ProxyClient {
    public static void main(String[] args) throws RemoteException, NotBoundException, MalformedURLException {
        MyRemote proxy = new Proxy();
        System.out.println(proxy.request(100));
    }
}
复制代码

 测试步骤:

  1、启动MyRemoteImpl 类的main方法,绑定远程对象到jvm。

  2、启动ProxyClient 类的main方法,对代理对象发起访问。

代码输出如下:

  MyRemoteImpl 类会输出:充值100元话费成功

  ProxyClient 类输出:充值成功

五、其他代理

  1、虚拟代理:可以作为创建开销大的对象的代表,虚拟代理让我们真正需要使用一个对象时才会去创建这个对象。在对象创建前和创建中,虚拟代理扮演真实对象的替身,当对象创建完毕后,虚拟代理会把请求直接委托给真实对象。虚拟代理在手机页面加载中经常可以见到,比如打开页面显示”**正在玩命加载中…”。

  2、缓存代理:可以理解成把网络上的静态资源或者不常改变的数据保存在本地,再次访问的这次数据的时候直接从本地读取。应用例子有页面的缓存机制、cdn、app缓存机制等。

  3、保护代理:根据角色或者其他机制控制用户对一些资源的访问权限。这常见于一些网站需要登录才能获取更多的内容,struts2和spring的拦截器等。

  4、静态代理:可以理解为对象由代理创建,在创建前后做一些事情,比如统计创建了多少对象,但静态代理只能创建一个或固定的几个对象。详见:http://blog.youkuaiyun.com/lidatgb/article/details/8941711。

  5、动态代理:其用途跟静态代理类型,但可以利用反射机制动态地创建对象,可以减少代理代码的重复,有更好的扩展性。详见:http://blog.youkuaiyun.com/lidatgb/article/details/8993131。

  6、正向代理:用户可以指定代理服务器转发请求到目标服务器完成,用户知道代理服务器地址和目标服务器地址。常见于FQ代理服务器。

  7、反向代理: 用户访问的目标服务器其实是代理服务器,代理服务器做负载均衡后把请求转发到真正的目标服务器执行。常见于负载均衡服务器。

六、使用场景

  由代理的概述中知道,但需要控制对资源或者对象的访问时使用代理模式。从代理的种类中可以进一步看清代理模式的使用场景,无非就是转发远程请求、作为创建开销大对象的替身、在本地保存网络资源、控制一些受保护资源的权限访问、作负载均衡。

代理模式是一种结构型设计模式,它提供一个代理对象来代表另一个对象。在代理模式中,有一个被称为实际对象(Subject)和一个被称为代理对象(Proxy)的中介,代理对象持有实际对象的引用,并且可以控制对实际对象的访问。代理模式的主要目的是在不修改原始对象的情况下,为原始对象添加额外的逻辑处理。 代理模式分为多种类型,如远程代理、虚拟代理、保护代理等,它们各自有不同的应用场景: - 远程代理:为远程对象提供一个本地代表。 - 虚拟代理:根据需要创建开销大的对象,通过虚拟代理控制访问这些对象的过程。 - 保护代理:控制对原始对象的访问权限,例如进行权限检查。 代理模式的优点包括: 1. 能够控制对真实对象的访问,并在访问前后添加额外的逻辑。 2. 可以通过代理对象实现延迟加载,即在实际需要时才创建真实对象。 3. 增强了对真实对象的封装,并且可以避免对真实对象的重复引用。 在C#中实现代理模式通常涉及以下步骤: 1. 定义一个接口或抽象类,声明真实对象和代理对象需要实现的方法。 2. 实现真实对象的类,按照接口或抽象类的要求实现具体方法。 3. 实现代理类,它同样实现接口或抽象类,并在方法中持有真实对象的引用,通过调用真实对象的方法来执行所需的操作,同时可以添加额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值