设计模式的艺术 结构性模式之代理模式

前言

现实中有些东西想要但是在别的国家想买但是过去买的成本太大,所以有中介这种行业应运而生,相对于自己去买的话比较便宜,也节省时间,在软件设计中,也存在着这么一种模式,客户端不能直接访问某个对象,此时可以通过一个称之为代理的第三章来实现间接访问,该方案对应的设计模式被称之为代理模式。

什么是代理模式 Proxy Pattern

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

代理模式的优点

(1)、代理模式1能够协调调用者与被调用者,在一定程度上降低了系统的耦合度,满足迪米特法则

(2)、客户端可以针对抽象主题角色进行编程,增加和更换代理类无须修改源代码,符合开闭原则,系统具有较好的灵活性和可扩展性

(3)、远程代理为位于两个不同地址空间对象的访问提供了一种实现机制,可以将一些消耗资源较多的对象和操作移至性能更好的计算机上,提高系统的整体运行效率

(4)、虚拟代理通过一个消耗资源较少的对象来代表一个消耗资源较多的对象,可以在一定程度上节省系统的运行开销

(5)、保护代理可以控制对一个对象的访问权限,为不同用户提供不同级别的使用权限

代理模式的缺点

(1)、由于在客户端和真实主题之间增加了代理对象,因此有些类型的的代理模式可能会造成请求的处理速度变慢,例如保护代理

(2)、实现代理模式需要额外的工作,有些代理模式的实现非常复杂,例如远程代理

代理模式的适用场景

代理模式的类型较多,所以可以根据不同的场景去适用

(1)、当客户端对象需要访问远程主机中的对象时,可以使用远程代理

(2)、当需要用一个消耗资源较少的对象来代表一个消耗资源较多的对象,从而降低系统开销、缩短运行时间时,可以使用虚拟代理,例如一个对象需要很长时间才能完成加载时

(3)、当需要控制对一个对象的访问,为不同用户提供不同级别的访问权限时,可以使用保护代理

(4)、当需要为某一个被频繁访问的操作结果提供一个临时存储空间,以供多个客户端共享访问这些结果时,可以使用缓冲代理,通过缓冲代理,系统无须再客户端每一次访问时都重新执行操作,只需要从临时缓冲区获取操作结果即可。

(5)、当需要为一个对象的访问提供一些额外操作时,可以使用智能引用代理。

代理模式的具体实现

目录结构

抽象主题类

package com.company;

//抽象查询类:抽象主题类
public interface Searcher {
    public String doSearch(String userId,String keyword);
}

真实主题类

//具体查询类:真实主题类
public class RealSearcher  {
    //模拟查询商务信息
    public String doSearch(String userId,String keyword){
        System.out.println("用户:"+userId+"使用关键词"+keyword+"查询商务信息");
        return  "返回具体内容";
    }
}

代理主题类

//代理查询类:代理主题类
public class ProxySearcher implements Searcher {
    private RealSearcher realSearcher=new RealSearcher();//维持一个对真实主题的引用
    private AccessValidator validator;
    private Logger logger;
    @Override
    public String doSearch(String userId, String keyword) {
        //如果身份验证成功,则执行查询
        if(validate(userId)){
            String result=realSearcher.doSearch(userId,keyword); //调用真实主题对象的查询方法
            this.log(userId);  //记录查询日志
            return  result;  //返回查询结果
        }else{
            return  null;
        }
    }
    //创建访问验证对象并调用其validate()方法实现身份验证
    public boolean validate(String userId){
        validator =new AccessValidator();
        return  validator.validate(userId);
    }
    //创建日志记录对象并调用其log()方法实现日志记录
    public void log(String userId){
        logger=new Logger();
        logger.log(userId);
    }
}

业务类

//日志记录类:业务类
public class Logger {
    //模拟实现日志记录类
    public void log(String userId){
        System.out.println("更新数据库,用户"+userId+"查询次数加1");
    }
}

身份验证类

//身份验证类:业务类
public class AccessValidator {
    //模拟实现登录验证
    public boolean validate(String userId){
        System.out.println("在数据库中验证用户"+userId+"是否是合法用户");
        if(userId.equalsIgnoreCase("杨过")){
            System.out.println(userId+"登录成功");
            return  true;
        }else{
            System.out.println(userId+"登录失败");
            return false;
        }
    }
}

客户端测试类

public class Client {

    public static void main(String[] args) {
   Searcher searcher;  //针对抽象编程,客户端无须分辨真实主题类和代理类
        searcher=(Searcher) XMLUtil.getBean();
        String result=searcher.doSearch("杨过","御女心经");
    }
}

转载请注明出处,掌声送给社会人

猜你喜欢

转载自blog.csdn.net/SCDN_CP/article/details/83039204