实例探索Java模式之路——代理模式

来源:互联网 发布:少帅汤玉麟 知乎 编辑:程序博客网 时间:2024/05/16 02:55
代理模式

在这里简单说一下代理模式,通过两个例子,来认识什么是代理模式。关于代理模式更多的介绍,以及更多的用途,以及在实际开发中,代理模式怎么用,可以查看Nginx有关的介绍,在那里我们详细介绍代理模式的动态代理。


1、代理模式是对象结构模式。代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。


2、代理模式结构:


抽象主体角色(代理对象和被代理对象共同的接口):声明了真实和代理主体的共同接口,这一来在任何可以使用真实主题的地方都可以使用代理主题。

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


3、一个例子:


//代理对象和被代理对象共同的接口
public abstract class Subject {


// 一个抽象的请求方法
public abstract void request();
}


//真实主题角色(被代理角色)
public class RealSubject extends Subject {


// 无参构造
public RealSubject() {
}


// 方法实现
@Override
public void request() {
System.out.println("From real subject");
}
}




//代理主题角色(代理角色)
public class ProxySubject extends Subject {
private RealSubject realsubject;


// 无参构造
public ProxySubject() {
}


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


realsubject.request();
postRequest();
}


// 请求之后的操作
private void postRequest() {
System.out.println("请求之后的操作");
}


// 请求之前的操作
private void preRequest() {
System.out.println("请求之前的操作");
}


}




//客户端
public class client {
public static void main(String[] args) {
// 将变量的明显类型声明为抽象主题的类型,而将其真实类型设置为代理主题类型。
Subject subject = new ProxySubject();
subject.request();
}
}


首先,代理主题并不改变主题接口,因为模式的用意是不让客户端感觉到代理存在;
其次,代理使用委派将客户端的调用委派给这是的主题对象,代理主题起到一个传递请求的作用;
最后,代理主题在传递请求之前和之后都可以执行特定的操作,而不是单纯传递请求。


4、代理模式依照目的可以分为:保护代理和智能引用代理
保护代理:一个代理对象对调用被代理对象的用户进行权限检查,并只允许有适当权限的用户调用原对象。
智能引用代理:一个代理对象对调用原对象的用户进行统计计数。


5、这是一个查询信息的例子,只有有相应的权限,才能进行查询得到查询结果,并记录查询次数。否则不给查询。


//抽象主体角色(代理对象和被代理对象共同的接口)
public interface Searcher {
// 一个抽象的请求方法
String doSearch(String userId, String searchType);
}




//真实主题角色(被代理角色)查询
public class RealSearch implements Searcher {


public RealSearch() {


}


// 真实的查询工作发生在这里
@Override
public String doSearch(String userId, String searchType) {
String sqlString = "SELECT * from table where key=" + searchType + "";


// 执行查询语句
return "result set(返回查询结果集)";


}


}


//代理主题角色(代理角色)
public class Proxy implements Searcher {


// 持有引用
private RealSearch search;
private UsageLogger usageLogger;
private AccessValidator accessValidator;


public Proxy() {
search = new RealSearch();
}


@Override
public String doSearch(String userId, String searchType) {
if (checkAccess(userId)) {
String result = search.doSearch(null, searchType);


logUsage(userId);
return result;
} else {
return "您的权限不足!";
}
}


// 查询后的日志操作
private void logUsage(String userId) {
usageLogger = new UsageLogger();
usageLogger.setUserId(userId);
usageLogger.save();


}


// 查询前的权限操作
private boolean checkAccess(String userId) {
accessValidator = new AccessValidator();
return accessValidator.validateUser(userId);
}


}


//记录次数用的类,
public class UsageLogger {
private String userId;


public void setUserId(String userId) {
this.userId = userId;
}


// 保存日志
public void save() {
String sqlString = "INSERT INTO TABLE (USE_ID) VALUES(" + userId + ")";


// 执行保存
System.out.println("保存操作日志成功");
}


public void save(String userId) {
this.userId = userId;
save();
}
}




public class AccessValidator {


// 用户权限检查发生在这


// 调用数据库方法,得到用户权限基础上在判断
public boolean validateUser(String userId) {
System.out.println("判断用户权限");
if (userId.equals("admin")) {
return true;
} else {
System.out.println("权限不足");
return false;
}
}
}


//客户端
public class client {
// 声明一个静态类型为Searcher的静态变量
private static Searcher searcher;


public static void main(String[] args) {
// 此静态变量的真实类型为Proxy
searcher = new Proxy();


String userId = "admin";
String searchType = "search_by_account_number";


String result = searcher.doSearch(userId, searchType);


System.out.println(result);
}

/*1、客户端调用代理对象;
2、代理对象调用AccessValidator对象,确定用户具有相应的权限
3、代理对象调用RealSearch对象,完成查询功能;
4、代理对象调用UsageLogger对象,完成计数功能;
5、代理对象将RealSearch对象的查询结果返回给客户端。*/
}



通过此实例,相信对该模式有了进一步的认识。

每天努力一点,每天都在进步。


原创粉丝点击