JAVA代理模式
通过本文将学习到
前言
前面一段时间辛辛苦苦把创建型的设计模式给抄了一遍,但是这远远不够!不过这也还好,毕竟我现在的理解都是基础需要不断的练习才能更好的理解!从今天开始进行结构型的设计模式学习。代理模式,就像是海淘代购之类的,一般就是客户买不到,或者不知道怎么买,所以同过代理(海外代购)来买。设计模式的代理模式与此作用相似!
1、代理模式的概念
代理模式:给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。
在软件开发中有可以提供与代购网站相似功能的设计模式,由于某些原因,客户端不想或者不能够直接访问一个对象,此时通过一个代理人的第三者来实现间接访问,这就是代理模式。
代理模式是一种应用广发的结构型设计模式,而且变化特别的多,常见的代理模式有远程代理、保护代理、虚拟代理、缓冲代理等。
2、代理模式的UML图
Subject(抽象主题角色):它申明了真实主题和代理主题的共同接口,这样一来在任何使用真实主题的地方都可以用代理主题,客户端通常需要针对抽象主题角色进行编程。
Proxy(代理主题角色):它包含了对真实主题的引用,从而可以在任何时候操作真实主题对象:在代理主题角色中提供了一个与真实主题角色相同的接口,以便在任何时候都可以代替真实主题,代理主题角色还可以控制对真实主题的使用,负责在需要的时候创建和删除真实主题对象,并对真实主题对象的使用加以约束。通常,在代理主题角色中客户端在调用所引用的真实主题操作之前或之后还需要执行其他操作,而不是仅仅是单纯调用真实主题对象的操作。
RealSubject(真实主题角色):它定义了代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作,客户端可以通过代理主题角色简介调用真实主题角色定义的操作。
3、代理模式的实现
在进行代理模式实现之前应该好好聊聊代理模式的UML图,虽然看上去代理模式也就3个角色,但是实际上代理模式的真实使用和实现过程还是非常复杂的,特别是代理类的设计和实现。
并且通过代理类的目的和实现方式不同可以分好多种类型。常见的有以下几种。我要好好说说!
1、远程代理(Remote Proxy):为一个不在同一地址空间的对象提供一个本地的代理对象,这个不同一空间可以是同一同电脑上不同地址,也可以是不同主机中。有点像VPN。
2、虚拟代理(Virtual Proxy):如果创建一个对象需要大量的资源的时候可以先创建一个相对小的对象进行表示,真实对象在使用的时候创建。有点像懒汉模式。
3、保护代理(Protext Proxy):对一个对象进行访问控制,可以给不同的角色分配不同的访问权限。
4、缓冲代理(Cache Proxy):为一个目标的操作结果开辟一个临时的空间存储,以便多个客户端共享使用。
做一个保护代理模式:
百度文档,通过一个保护代理来验证你是否为VIP,如果是VIP可以通过代理来看,不是那就不能下载。
AccessVaildator:身份验证类(业务类),它提供了validate()方法来实现身份验证。
package proxyPattern;
/**
*
* <p>Title: AccessValidator</p>
* <p>Description: 身份验证类,它提供Validate()方法来进行身份呢验证</p>
* @author HAND_WEILI
* @date 2018年9月4日
*/
public class AccessValidator {
//实际业务中需要通过数据库动态的获取数据,现在只是模拟
public boolean validate(String name) {
System.out.println("验证用户"+name+"是否为VIP用户");
if(name.equals("帅哥威")) {
System.out.println("尊敬的"+name+"欢迎您使用百度文档");
return true;
}else {
System.out.println("狗JB"+name+"不是会员还想下载,滚!");
return false;
}
}
}
Logger:日志记录类(业务类),它提供了Log()方法来保存日志.
package proxyPattern;
/**
*
* <p>Title: Logger</p>
* <p>Description: 日志类来记录操作</p>
* @author HAND_WEILI
* @date 2018年9月4日
*/
public class Logger {
public void log (String name ) {
System.out.println("更新数据库,用户"+name+"下载次数+1");
}
}
DownLoadFile:下载类,充当抽象主题类,申明了下载方法。
package proxyPattern;
/**
*
* <p>Title: DownLoadFile</p>
* <p>Description:抽象主题类,声明下载方法 </p>
* @author HAND_WEILI
* @date 2018年9月4日
*/
public interface DownLoadFile {
public String downLoad(String name,String key);
}
RealDownLoadFile:真实下载类,实现下载的功能
package proxyPattern;
public class RealDownLoadFile implements DownLoadFile {
@Override
public String downLoad(String name, String key) {
// TODO Auto-generated method stub
System.out.println("用户"+name+"下载了"+key+"文件");
return "返回具体文件!";
}
}
ProxyDownLoad:代理下载类,充当代理主题角色,它是下载代理,保护代理!
package proxyPattern;
/**
*
* <p>Title: ProxyDownLoad</p>
* <p>Description: 代理下载类</p>
* @author HAND_WEILI
* @date 2018年9月4日
*/
public class ProxyDownLoad implements DownLoadFile{
private RealDownLoadFile realDownLoadFile = new RealDownLoadFile();
private AccessValidator accessValidator;
private Logger logger;
@Override
public String downLoad(String name, String key) {
//调用判断方法
if(this.validate(name)) {
//如果成功调用
String result =realDownLoadFile.downLoad(name, key);
this.log(name);
return result;
}else {
return "验证不通过";
}
}
//身份验证
public boolean validate(String name) {
accessValidator = new AccessValidator();
boolean f = accessValidator.validate(name);
return f;
}
//log
public void log(String name) {
logger = new Logger();
logger.log(name);
}
}
config.xml:配置文件
<?xml version="1.0"?>
<config>
<className>proxyPattern.ProxyDownLoad</className>
</config>
XMLUtils:工具类。
package proxyPattern;
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class XMLUtils {
public static Object getProxyPatten() {
try {
//获取xml文档
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc;
doc = dBuilder.parse(new File("src//proxyPattern//config.xml"));
//通过类名文本节点
NodeList list = doc.getElementsByTagName("className");
Node node =list.item(0).getFirstChild();
String cName = node.getNodeValue();
//通过类名生成实例并放回
Class c = Class.forName(cName);
Object obj = c.newInstance();
return obj;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
}
客户端:客户端测试类。
package proxyPattern;
public class Client {
public static void main(String[] args) {
DownLoadFile dlf;
dlf=(DownLoadFile)XMLUtils.getProxyPatten();
String result = dlf.downLoad("帅哥威", "《人在江湖飘,哪有不挨刀“》");
}
}
4、代理模式的优缺点
优点:
- 能够协调调用者和被调用者,在一定程度上降低了系统的耦合度。
- 客户端可以针对抽象主题类进行编程,可以通过配置信息修改代理类,而无需修改源代码,符合开闭原则!让系统可扩展性和灵活性更好。
缺点:
- 由于客户端和真实主题类增加了代理类,因此访问的速度可能会降低。比如保护类,需要进行校验会在一定程度上影响访问速度。
- 实现代理类需要而外的工作量,并且有些代理类实现起来非常复杂比如远程代理类!
5、代理模式的适用场景
- 客户端需要访问远程主机的对象的时候可以用远程代理类。
- 当需要进行通过角色进行访问控制的时候可以使用保护代理类。
- 当需要访问一个对象,并且作而外操作的时候可以使用智能代理类。
6、总结
代理类中有一个非常重要的用途就是动态代理AOP。这一块需要作一个专门的博客来记录。其次,代理模式作为权限控制还是非常好的一个概念。通过角色来分权限!今天看到了一些博客,说的非常好,我想分享下!我们现在学习的只是使用,框架的使用。但事实上我们作为一个程序员应该更加,关注数据结构,算法,编译原理,计算机原理。计算机网络!因为这些是实现框架,甚至编程语言的基础!框架迭代速度非常快,有必要全部去学习么?显然,这不是正解!应该这么解释,框架就相当于一种优美的字体,但是算法,数据结构等等基础就相当于笔画!如果只是去学一个框架的话,就好比掌握了一种字体。但是如果学会了基础笔画,我们就可以通过自己来创造字体。所以综上所述,我们看似无用的计算基础实则是让自己从一个使用者转变成创造者的一个过程。当然这只是我得粗鄙之见,在我以后的学习中肯定会有不同的感受,不过学习计算机的路可停不下来哦!亲。
另外,现在!我主要差的就是实战,就是干出东西,通过实物来驱动,比通过理论驱动更有意思加油老铁!JUST FOR FUN 。linux还给别人打过工了!