智能引用代理

       我们先看这么一个问题:一个网站,用户所做的操作基本上就是搜索和查询。由于网站提供的信息是极有价值的商业信息,因此这个网站是一个收费的B2B 网站。在这里收费,意味着两个问题:一是必须对用户的身份进行检查,二是要对用户的使用次数进行统计,以便按照收费标准进行收费。
       代理模式按照目的可以分为几种,其中有保护代理和智能引用代理两种。
       保护代理:一个代理对象对调用被代理对象的用户进行权限检查,并且只允许有适当权限的用户调用原对象。
       智能引用代理:一个代理对象对调动原对象的用户进行统计计数。
       很明显,以上两种代理模式正式问题的解决方案。

                       系统设计
第一步:抽象和具体的划分
       首先系统需要一个进行查询的类。根据开-闭原则,设计应当有一个抽象角色和一个具体角色,抽象角色给出接口声明,将实现的细节交给具体角色。这样当有新的查询功能时,只需要创建一个新的具体角色即可。这样就可以在不需要修改代码的情况下,增加新的查询功能。
第二步:辅助功能的提供      
       系统必须有两个辅助对象:一个用来检测用户的权限,称为AccessValidator;另一个用做查询的计数器,称为UsageLogger。
       这两个辅助对象分别提供适当的方法检查用户的权限和将查询事件记录到数据库中。
第三步:引入代理角色
       基本的功能现在都由确定的对象提供了:查询功能由RealSearcher对象提供;检查用户权限由 AccessValidator对象提供,记录查询次数的功能由 UsageLogger对象提供。
      一个没有代理模式知识和应用代理模式经营的设计师往往就停在这里了,因为人们往往会认为只要修改一下RealSearcher对象的方法,在查询操作之前进行权限检查,在查询之后进行查询次数的记录就可以了。可以是可以了,只是不够好。因为RealSearcher对象检查对自己的调用不够安全,这个检查应该在RealSearcher对象之外的某个地方:而且RealSearcher对象可以会有不止一个方法需要进行调用权限检查,每一个方法都需要自行检查,这样会使检查的逻辑出现在数个地方,易于出错,且不易维护,这是其一。
       其二,对权限的检查和记录调用的次数的责任属于对RealSearcher对象的调用控制,这个责任应当与RealSearcher对象本身分开。换而言之,系统应当为RealSearcher对象提供一个代理对象,由代理负责这两项工作,并将调用委派给RealSearcher对象。如下设计图:
                                 智能引用代理

       代理对象Proxy持有对RealSearcher对象、AccessValidator对象和UsageLogger 对象的引用。
     
系统的时序
      如下图所示,此时序图清晰给出了调用发生的顺序:       
     (1)客户端调用代理对象;
     (2)代理对象调用AccessValidator对象,确认用户确实具有相应的权限;
     (3)代理对象调用RealSearcher对象,完成查询功能;
     (4)代理对象调用UsageLogger对象,完成计数功能;
     (5)代理对象将RealSearcher对象的查询结果返回给客户端。
                 智能引用代理
       
         系统源码
1. 客户端代码:Client.java

package com.design.mode.proxy.smartproxy;

/**
 * 客户端源代码
 * */
public class Client {
	
	//声明一个静态类型为Searcher的静态变量
	private static Searcher searcher;
	public static void main(String[] args) {
		searcher = new Proxy();
		String userId ="000001";
		try{
			String result = searcher.doSearch(userId);
			System.out.println("============"+result);
		}catch(Exception ex){
			ex.printStackTrace();
		}
	}
}
2.抽象主题代码:Searcher.java
package com.design.mode.proxy.smartproxy;

/**
 * 抽象主题角色
 * */
public interface Searcher {
	
	//声明一个抽象方法
	public String doSearch(String userId) throws Exception;

}
3.代理角色代码:Proxy.java
package com.design.mode.proxy.smartproxy;


/**
 * 代理角色源代码
 * */
public class Proxy implements Searcher{
	
	private RealSearcher searcher;
	private AccessValidator accessValidator;
	private UsageLogger usageLogger;
	
	/**
	 * 构造子
	 * */
	public Proxy(){
		searcher = new RealSearcher();
	}
	
	//查询前的权限操作
	private boolean checkAccess(String userId){
		accessValidator = new AccessValidator();
	 	boolean bo= accessValidator.vaidate(userId);
		return bo;
	}
	
	//查询后,将记录写入日志
	private void logUsage(String userId){
		usageLogger =new UsageLogger();
		usageLogger.setUserId(userId);
		usageLogger.save();
	}
	
	public String doSearch(String userId) throws Exception {
		if(checkAccess(userId)){
			String result = searcher.doSearch(userId);
			logUsage(userId);
			return result;
		}
		return null;
	}

}
4.真实主题代码:RealSearcher.java
package com.design.mode.proxy.smartproxy;

/**
 * 真实主题角色
 * */
import com.design.mode.proxy.dao.DbJavabean;


public class RealSearcher implements Searcher {

	
	//构造函数
	public RealSearcher(){
		
	}
	
	public String doSearch(String userId) throws Exception {
		
		DbJavabean db = new DbJavabean();
		String str=db.selUserMsg(userId);
		return str;
	}
}
5.检查权限的对象的代码:AccessValidator.java
package com.design.mode.proxy.smartproxy;

import com.design.mode.proxy.dao.DbJavabean;


/**
 * 检查权限
 * */
public class AccessValidator {
	
	public boolean vaidate(String userId){
		
		DbJavabean db = new DbJavabean();
		String userType = db.selUserType(userId);
		if(userType.equals("admin")){
			return true;
		}else
		   return false;
	}

}
6.记录次数的代码:UsageLogger.java
package com.design.mode.proxy.smartproxy;

import com.design.mode.proxy.dao.DbJavabean;

/**
 * 记录次数代码
 * */
public class UsageLogger {
	
	private String userId;
	/**
	 * 用户的赋值方法
	 * */
	public void setUserId(String userId){
		this.userId = userId;
	}
	
	public void save(){
		DbJavabean db = new DbJavabean();
		db.upCount(userId);
	}
}
7.数据库连接的类 DbJavabean.java 
package com.design.mode.proxy.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class DbJavabean {
	
	public String conndb(String sql,int x) throws Exception{
		Connection conn = null;
		String userType ="";
		try{
			Class.forName("oracle.jdbc.driver.OracleDriver");
			String url ="jdbc:oracle:thin:@10.10.9.110:1521:infonet";
			String user="infonet";
			String password ="infonet2";
			conn = DriverManager.getConnection(url, user, password);
			//Statement st = conn.createStatement();
			//PreparedStatement 接口继承Statement PreparedStatement对象已预编译过效率要快于Statement
			PreparedStatement st = conn.prepareStatement(sql);
			if(x==0){
				//st.executeQuery(sql);
				st.executeQuery();
				ResultSet rs = st.getResultSet();
				while(rs.next()){
					userType = rs.getString("userMsg");
				}
			}else if(x==1){
				st.executeQuery(sql);
				ResultSet rs = st.getResultSet();
				while(rs.next()){
					userType = rs.getString("userType");
				}
			}else{
			  userType = st.executeUpdate(sql)+ "";
			}
			conn.commit();
			st.close();
			conn.close();
		}catch(Exception ex){
			ex.printStackTrace();
			throw ex;
		}finally{
			conn.close();
		}
		return userType;
	}

	
	
	//查询用户状态
	public String selUserType(String userId){
		int x = 1;
		String userType="";
		String sql ="select usertype from proxy_demo_user pu where pu.userId ="+userId;
		try{
			userType=conndb(sql, x);
		}catch(Exception ex){
			ex.printStackTrace();
		}
		return userType;
	}
	
	//查询用户信息
	public String selUserMsg(String userId){
		int x =0;
		String userMsg="";
		String sql ="select usermsg from proxy_demo_user pu where pu.userId = "+userId;
		try{
			userMsg=conndb(sql, x);
		}catch(Exception ex){
			ex.printStackTrace();
		}
		return userMsg;
	}
	
	
	
	//记录用户次数
	public void upCount(String userId){
		int x = 2;
		String sql ="update proxy_demo_user  pu set pu.usercount = pu.usercount +1 where pu.userId ="+userId;
		try{
			conndb(sql, x);
		}catch(Exception ex){
			ex.printStackTrace();
		}
	}
	
}














你可能感兴趣的:(智能引用代理)