《设计模式》学习笔记--代理Proxy

 

1、官方描述:
    为其他对象提供一种代理以控制对这个对象的访问。
 
2、实例讨论:
在进行应用系统开发的时候,往往会有一些信息在部署时才能够确定,并且可能会根据情况进行调整,如数据库配置信息等等,如果把这些信息直接硬编码到程序中,在需要调整时就不得不对系统进行重新编译和发布,这样不仅很麻烦,而且如果系统已经交付给用户使用,那么更是极其的不方便。
怎样解决这些配置信息问题呢,使其既便于修改,而又不对系统产生影响?一个可行的方案是把这些信息写到配置文件中,如Java项目可以写到XML文件或properties文件中,系统在需要这些信息时可以读取配置文件进行获取,这样当需要对配置信息进行调整时可以直接修改这些文件内容,而系统无需再进行编译和发布,这对于已经交付给用户的系统来说无疑也非常的方便。
那么这些信息如何获取呢?每次需要时都直接读取配置文件吗?因为这些配置信息可能会频繁的使用,如果每次都要读取配置文件,那么性能开销将是很大的。这是我们就可以采用Proxy模式,在数据访问对象上进行代理访问,每次需要这些配置信息时,都通过访问代理进行获取,访问代理判断是否已经访问过配置文件并缓存了配置信息,如果已经缓存了,就直接返回缓存的信息,否则在通过真正的DAO进行读取,这个配置文件数据访问模块类结构图如下:
 
 
3、代理类型:
Proxy模式在访问对象时提供了一定程度的间接性,这种间接性可以帮助解决某些问题,不同的Proxy解决不同类型的问题,在GOF设计模式中列举了四种代理类型,分别如下:
1)远程代理(Remote Proxy),为一个对象在不同的地址空间提供本地代表;
2)虚代理(Virtual Proxy),根据需要创建开销很大的对象;
3)保护代理(Protection Proxy),控制对原始对象的访问,用于不同的客户端有不同的访问权限;
4)智能指针(Smart Reference),取代了简单指针,在访问对象时执行一些附加操作;
在上面讨论的系统配置信息代理访问ConfigDAOProxy,属于4)智能指针的类型,在这里进行数据缓存以提高数据访问性能的附加能力。
 
4、实现特征:
1)Proxy和被代理的实体具有相同的接口Subject,这样在被代理实体可以使用的地方就可以用Proxy进行代替;
2)Proxy具有被代理实体的一个引用,以便在需要时把客户端的请求转发给真正的实体;
 
5、Java代码演示:
下面代码演示了在上面“实例讨论”部分中配置文件读取模块的Java代码结构:
类DataBaseConfig,数据库配置信息值对象:
 
package  qinysong.pattern.proxy;

// 值对象,数据库配置信息 
public   class  DataBaseConfig  {
  
private String dateBaseUrl;
  
private String dateBaseName;
  
private String userName;
  
private String password;

  
public String getDateBaseUrl() {
    
return dateBaseUrl;
  }

  
public void setDateBaseUrl(String dateBaseUrl) {
    
this.dateBaseUrl = dateBaseUrl;
  }


  
//.......
}

 
接口ConfigDAO,获取配置信息的数据访问接口:
 
package  qinysong.pattern.proxy;

public   interface  ConfigDAO  {
  
public DataBaseConfig getDataBaseConfig();
}

 
类ConfigDAOImp,实现ConfigDAO,进行实际的从配置文件中读取配置信息操作:
 
package  qinysong.pattern.proxy;

public   class  ConfigDAOImp  implements  ConfigDAO  {

  
//通过配置文件读取数据库配置信息
  public DataBaseConfig getDataBaseConfig(){
    System.out.println(
"ConfigDAOImp.getDataBaseConfig 调用");
    DataBaseConfig dataBaseConfig 
= new DataBaseConfig();
    
//通过配置文件设置dataBaseConfig数据
    
//......
    return dataBaseConfig;
  }

}

 
类ConfigDAOProxy,数据访问代理,实现ConfigDAO,通过ConfigDAOImp进行首次配置信息读入,并加以缓存,以后访问直接从缓存返回,提高系统性能:
 
package  qinysong.pattern.proxy;

import  java.util.HashMap;

public   class  ConfigDAOProxy  implements  ConfigDAO  {

  
//缓冲容器,保存已经读取过的配置信息
  private static HashMap configs = new HashMap();
  
//数据访问实体的引用,以便必要时进行调用
  private ConfigDAO configDAO;

  
//获得数据库配置信息的代理方法,若已经获取则直接返回,若首次获取则调用DAO进行获取
  public DataBaseConfig getDataBaseConfig(){
    System.out.println(
"ConfigDAOProxy.getDataBaseConfig 调用");
    
if (configs.containsKey("dataBaseConfig")){
      
return (DataBaseConfig) configs.get("dataBaseConfig");
    }
 else {
      configDAO 
= new ConfigDAOImp();
      DataBaseConfig dataBaseConfig 
= configDAO.getDataBaseConfig();
      configs.put(
"dataBaseConfig", dataBaseConfig);
      
return dataBaseConfig;
    }

  }

}

 
类Client,客户端代码,这里对上面的类进行使用演示:
 
package  qinysong.pattern.proxy;

public   class  Client  {
  
public static void main(String[] args) {
    System.out.println(
"Client.main begin ......");
    ConfigDAO configDao 
= new ConfigDAOProxy();
    System.out.println(
"Client.main 首次调用");
    DataBaseConfig databaseConfig 
= configDao.getDataBaseConfig();
    System.out.println(
"Client.main 再次调用");
    databaseConfig 
= configDao.getDataBaseConfig();
    System.out.println(
"Client.main end   ......");
  }

}

 
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值