博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
代理模式(Proxy)
阅读量:6024 次
发布时间:2019-06-20

本文共 3838 字,大约阅读时间需要 12 分钟。

转载

某软件公司承接了某信息咨询公司的收费商务信息查询系统的开发任务,该系统的基本需求如下:

(1) 在进行商务信息查询之前用户需要通过身份验证,只有合法用户才能够使用该查询系统;

(2) 在进行商务信息查询时系统需要记录查询日志,以便根据查询次数收取查询费用。

该软件公司开发人员已完成了商务信息查询模块的开发任务,现希望能够以一种松耦合的方式向原有系统增加身份验证和日志记录功能,客户端代码可以无区别地对待原始的商务信息查询模块和增加新功能之后的商务信息查询模块,而且可能在将来还要在该信息查询模块中增加一些新的功能。

试使用代理模式设计并实现该收费商务信息查询系统。

  1. 实例分析及类图

通过分析,可以采用一种间接访问的方式来实现该商务信息查询系统的设计,在客户端对象和信息查询对象之间增加一个代理对象,让代理对象来实现身份验证和日志记录等功能,而无须直接对原有的商务信息查询对象进行修改,如图1-1所示:

img_d2852ee7a9d0ed4f38b28a5d958d1005.png
1-1.png

在图中,客户端对象通过代理对象间接访问具有商务信息查询功能的真实对象,在代理对象中除了调用真实对象的商务信息查询功能外,还增加了身份验证和日志记录等功能。使用代理模式设计该商务信息查询系统,结构图如图1-2所示。

img_ce723fadae8ab748ca576b6d91564431.png
1-2.png

在图1-2中,业务类AccessValidator用于验证用户身份,业务类Logger用于记录用户查询日志,Searcher充当抽象主题角色,RealSearcher充当真实主题角色,ProxySearcher充当代理主题角色

  1. 实例代码
    (1) AccessValidator:身份验证类,业务类,它提供方法Validate()来实现身份验证。
//AccessValidator.csusing System; namespace ProxySample{    class AccessValidator    {        //模拟实现登录验证        public bool Validate(string userId)         {            Console.WriteLine("在数据库中验证用户'" + userId + "'是否是合法用户?");            if (userId.Equals("杨过")) {                Console.WriteLine("'{0}'登录成功!",userId);                return true;            }            else {                Console.WriteLine("'{0}'登录失败!", userId);                return false;            }        }    }

(2) Logger:日志记录类,业务类,它提供方法Log()来保存日志。

//Logger.csusing System; namespace ProxySample{    class Logger    {        //模拟实现日志记录        public void Log(string userId) {            Console.WriteLine("更新数据库,用户'{0}'查询次数加1!",userId);        }    }}

(3) Searcher:抽象查询类,充当抽象主题角色,它声明了DoSearch()方法。

namespace ProxySample{    interface Searcher    {        string DoSearch(string userId, string keyword);    }}

(4) RealSearcher:具体查询类,充当真实主题角色,它实现查询功能,提供方法DoSearch()来查询信息。

//RealSearcher.csusing System; namespace ProxySample{    class RealSearcher : Searcher    {        //模拟查询商务信息        public string DoSearch(string userId, string keyword) {            Console.WriteLine("用户'{0}'使用关键词'{1}'查询商务信息!",userId,keyword);            return "返回具体内容";        }    }}

(5) ProxySearcher:代理查询类,充当代理主题角色,它是查询代理,维持了对RealSearcher对象、AccessValidator对象和Logger对象的引用。

namespace ProxySample{    class ProxySearcher : Searcher    {        private RealSearcher searcher = new RealSearcher(); //维持一个对真实主题的引用        private AccessValidator validator;        private Logger logger;         public string DoSearch(string userId, string keyword)        {            //如果身份验证成功,则执行查询            if (this.Validate(userId))            {                string result = searcher.DoSearch(userId, keyword); //调用真实主题对象的查询方法                this.Log(userId); //记录查询日志                return result; //返回查询结果            }            else            {                return null;            }        }         //创建访问验证对象并调用其Validate()方法实现身份验证        public bool Validate(string userId)        {            validator = new AccessValidator();            return validator.Validate(userId);        }         //创建日志记录对象并调用其Log()方法实现日志记录        public void Log(string userId)        {            logger = new Logger();            logger.Log(userId);        }    }}

(6) 配置文件App.config,在配置文件中存储了代理主题类类名。

(7) Program:客户端测试类

//Program.csusing System;using System.Configuration;using System.Reflection; namespace ProxySample{    class Program    {        static void Main(string[] args)        {            //读取配置文件            string proxy = ConfigurationManager.AppSettings["proxy"];             //反射生成对象,针对抽象编程,客户端无须分辨真实主题类和代理类            Searcher searcher;            searcher = (Searcher)Assembly.Load("ProxySample").CreateInstance(proxy);             String result = searcher.DoSearch("杨过", "玉女心经");            Console.Read();        }    }}

结果及分析

在数据库中验证用户'杨过'是否是合法用户?

'杨过'登录成功!
用户'杨过'使用关键词'玉女心经'查询商务信息!
更新数据库,用户'杨过'查询次数加1!

本实例是保护代理和智能引用代理的应用实例,在代理类ProxySearcher中实现对真实主题类的权限控制和引用计数,如果需要在访问真实主题时增加新的访问控制机制和新功能,只需增加一个新的代理类,再修改配置文件,在客户端代码中使用新增代理类即可,源代码无须修改,符合开闭原则。

你可能感兴趣的文章
(二)nimlang web开发 hello world jester
查看>>
check_traffic.sh监控格式为Hex-STRING的解决办法
查看>>
经过五年测试 维基利用HTML5迈入视频时代
查看>>
MFC中CString.format用法
查看>>
MongDB与Spring整合及操作
查看>>
ListView数据项隔行换色控制实现详解
查看>>
我是如何阅读编程书的
查看>>
环境搭建之八-- node.js, npm和yarn
查看>>
iOS开发 - 百度地图后台持续定位
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
红帽企业版6.0 KVM虚拟化实战攻略02
查看>>
CentOS 7.3 源码安装 OpenVAS 9
查看>>
log4j.properties配置详解与实例
查看>>
fail2ban-0.8.14 shell自动部署脚本
查看>>
网络接口
查看>>
TCP/UDP端口列表
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
zabbix配置外部邮件服务器进行邮件报警
查看>>