代理模式是一种结构型设计模式,它使用一个代理类来访问需要访问的真实对象,为了保证客户端使用的透明性,所访问的真实对象与代理对象需要实现相同的接口。
- 为什么要使用这个模式:
在某些情况下,客户不能或者不想直接引用访问一个对象,在这样的要求下我们可以引入一个代理类来实现间接引用。代理类在客户端和真实访问对象之间起一个中介的作用,并且可以通过代理对象去掉客户端不能看到的内容或者添加一些逻辑判断等其他的服务。
- 代理模式定义:
给某一个对象提供一个代理,并由代理对象控制对原对象的引用。
- 模式结构:
Subject(抽象主题角色):声明了真实主题和代理主题的共同接口,这样一来在任何使用真实主题的地方都可以使用代理主题,客户端通常需要针对抽象主题角色进行编程。
Proxy(代理主题角色):包含了对真实主题的引用,从而可以在任何时候操作真实主题对象。在代理主题角色中提供一个与真实主题角色相同的接口,以便在任何时候都可以替代真实主体。代理主题角色还可以控制对真实主题的使用,负责在需要的时候创建和删除真实主题对象,并对真实主题对象的使用加以约束。代理主题角色通常在客户端在调用所引用的真实主题操作之前或之后还需要执行其他操作,而不仅仅是单纯调用真实主题对象中的操作。
RealSubject(真实主题角色):定义了代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作,客户端可以通过代理主题角色间接调用真实主题角色中定义的方法。
下面通过一个实例来理解代理模式:
在一个论坛中已注册用户和游客的权限不同,已注册的用户拥有发帖、修改自己的注册信息、修改自己的帖子等功能;而游客只能看到别人发的帖子,没有其他权限。使用代理模式来设计该权限管理模块。
Subject(抽象主题角色):AbstractPermission.java
package com.subject;
/**
*
* @ClassName: AbstractPermission
* @Description: TODO
* @author: BeatificCat
* @date: 2018年4月24日 下午11:26:54
*/
public interface AbstractPermission {
public void modifyUserInfo();
public void viewNote();
public void publishNote();
public void modifyNote();
public void setLevel(int level);
}
RealSubject(真实主题角色):RealPermission.java
package com.realSubject;
import com.subject.AbstractPermission;
/**
*
* @ClassName: RealPermission
* @Description: TODO
* @author: BeatificCat
* @date: 2018年4月24日 下午11:27:01
*/
public class RealPermission implements AbstractPermission {
@Override
public void modifyUserInfo() {
// TODO Auto-generated method stub
System.out.println("修改用户信息");
}
@Override
public void viewNote() {
// TODO Auto-generated method stub
}
@Override
public void publishNote() {
// TODO Auto-generated method stub
System.out.println("发布内容");
}
@Override
public void modifyNote() {
// TODO Auto-generated method stub
System.out.println("修改内容");
}
@Override
public void setLevel(int level) {
// TODO Auto-generated method stub
}
}
Proxy(代理主题角色):ProxyPermission.java
package com.proxy;
import com.realSubject.RealPermission;
import com.subject.AbstractPermission;
/**
*
* @ClassName: ProxyPermission
* @Description: TODO
* @author: BeatificCat
* @date: 2018年4月24日 下午11:27:10
*/
public class ProxyPermission implements AbstractPermission {
private RealPermission rp = new RealPermission();
private int level = 0;
@Override
public void modifyUserInfo() {
// TODO Auto-generated method stub
if (level == 0) {
System.out.println("limited authority");
}else if (level == 1) {
rp.modifyUserInfo();
}
}
@Override
public void viewNote() {
// TODO Auto-generated method stub
System.out.println("查看内容");
}
@Override
public void publishNote() {
// TODO Auto-generated method stub
if (level == 0) {
System.out.println("limited authority");
}else if (level == 1) {
rp.publishNote();
}
}
@Override
public void modifyNote() {
// TODO Auto-generated method stub
if (level == 0) {
System.out.println("limited authority");
}else if (level == 1) {
rp.modifyNote();
}
}
@Override
public void setLevel(int level) {
// TODO Auto-generated method stub
this.level = level;
}
}
Client(客户端):Client.java
package com.client;
import com.proxy.ProxyPermission;
import com.subject.AbstractPermission;
/**
*
* @ClassName: Client
* @Description: TODO
* @author: BeatificCat
* @date: 2018年4月24日 下午11:29:38
*/
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
AbstractPermission abstractPermission = new ProxyPermission();
abstractPermission.modifyUserInfo();
abstractPermission.viewNote();
abstractPermission.publishNote();
abstractPermission.modifyNote();
System.out.println("----------->");
abstractPermission.setLevel(1);
abstractPermission.modifyUserInfo();
abstractPermission.viewNote();
abstractPermission.publishNote();
abstractPermission.modifyNote();
}
}
- 代理模式的优点:
代理模式的优点在于能够协调调用者和被调用者,在一定程度上降低了系统的耦合度。
- 代理模式的缺点:
代理模式的缺点在于由于客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢,并且实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
- 模式适用环境:
(1) 远程(Remote)代理:为一个位于不同的地址空间的对象提供一个本地的代理对象,这个不同的地址空间可以是在同一台主机中,也可是在另一台主机中。
(2) 虚拟(Virtual)代理:如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。
(3)Copy-on-Write代理:它是虚拟代理的一种,把复制(克隆)操作延迟到只有在客户端真正需要时才执行。一般来说,对象的深克隆是一个开销较大的操作,Copy-on-Write代理可以让这个操作延迟,只有对象被用到的时候才被克隆。
(4) 保护(Protect or Acess)代理:控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。
(5) 缓冲(Cache)代理:为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。
(6) 防火墙(Firewall)代理:保护目标不让恶意用户接近。
(7) 同步化(Synchronization)代理:使几个用户能够同时使用一个对象而没有冲突。
(8) 智能引用(Smart Reference)代理:当一个对象被引用时,提供一些额外的操作,如将此对象被调用的次数记录下来等。
在这些种类的代理中,虚拟代理、远程代理和保护代理是最常见的代理模式。不同类型的代理模式有不同的优缺点,它们应用于不同的场合。