`

设计模式之 Proxy - 代理模式

阅读更多

Proxy模式也叫代理模式,是由GoF提出的23种软件设计模式的一种。本文介绍设计模式中的装饰(Proxy)模式的概念,用法,以及实际应用中怎么样使用代理模式进行开发。

Proxy模式的概念

Proxy模式是构造型的设计模式之一,它可以为其他对象提供一种代理(Proxy)以控制对这个对象的访问。
所谓代理,是指具有与代理元(被代理的对象)具有相同的接口的类,客户端必须通过代理与被代理的目标类交互,而代理一般在交互的过程中(交互前后),进行某些特别的处理。
根据这些“特别处理”的不同,有以下几种常见的代理模式
- Remote proxy:远程代理。该代理可以让客户端透明地引用一个存在于不同地址空间(远程或本地)的对象。
- Virtual proxy:虚拟代理。该代理允许一个对象只有在真正被用到时才被创建。
- Copy-on-write proxy:对象拷贝延迟代理。该代理可以延迟一个对象的拷贝(clone)操作到客户调用里,它是virtual proxy模式的一种特殊情况。一般来说,对象的深度克隆是一个高开销的动作,该代理可以让这个动作延迟,只有对象被用到的时候才被克隆。
- Protection (access) proxy:访问保护代理。该代理可以在访问一个对象时附加一些检查操作,比如权限验证等。
- Cache proxy:缓存代理。主要为那些创建时高开销的对象提供缓存,以供多客户端共享。
- Firewall proxy:防火墙代理。保护目标对象不受某些不良客户端的侵害。
- Synchronization proxy:为非同步的目标对象提供并发控制。
- Smart reference proxy:当一个对象被引用时提供某些额外的操作。比如对象被引用时,记录对象被引用的次数等。


Proxy模式的类图描述:

[出自:wikimedia.org]

Subject
被代理的类的接口。
Proxy
代理类。该代理类实现了Subject接口。
RealSubject
代理元,即被代理的目标类。它实现了Subject接口。


Proxy模式的应用范例
下面,我们实现一个Protection (access) proxy:
在该范例中,我们模拟了一个现实应用中使用代理控制对数据库表FILE_TBL的操作。当一个用户具有足够的权限时,则可以进行修改删除等操作。否则,打印权限不够的错误信息。
文件一览:
Client
    测试类
FileTbl
    与数据库表FILE_TBL相对应的数据类
Permission
    权限控制
FileTblDao
    操作数据库表FILE_TBL的DAO接口
FileTblDaoImpl
    操作数据库表FILE_TBL的DAO接口的一个标准实现
FileTblDaoProxy
    FileTblDaoImpl的一个代理类。通过该代理类,控制用户进行不同的操作

public class Client {
    /**
     * for test
     */

    public static void main(String[] args) {
        //只读权限的用户
        Permission searchPermission = new Permission(Permission.PERMISSION.SEARCH);
        FileTblDao searchDao = new FileTblDaoProxy(searchPermission);
        FileTbl fileTbl = searchDao.getFile("file01");
        //只读权限的用户修改文件
        searchDao.updateFile(fileTbl);
        
        //全权限的用户
        Permission allPermission = new Permission(Permission.PERMISSION.ALL);
        FileTblDao allDao = new FileTblDaoProxy(allPermission);
        //全权限的用户修改文件
        allDao.updateFile(fileTbl);
    }

}


/**
* Subject
* 操作文件表的DAO
*/

interface FileTblDao {
    public void deleteFile(FileTbl fileTbl);
    public void updateFile(FileTbl fileTbl);
    public void saveFile(FileTbl fileTbl);
    public FileTbl getFile(String fileId);
}

/**
* RealSubject
* 操作文件表的DAO的一个标准实现
*/

class FileTblDaoImpl implements FileTblDao {

    public void deleteFile(FileTbl fileTbl) {
        System.out.println("delete file:" + fileTbl.getId());        
    }

    public void updateFile(FileTbl fileTbl) {
        System.out.println("update file:" + fileTbl.getId());
    }

    public void saveFile(FileTbl fileTbl) {
        System.out.println("save file:" + fileTbl.getId());
    }

    public FileTbl getFile(String fileId) {
        return new FileTbl(fileId);
    }
    
}

/**
* Proxy
* 操作文件表的DAO代理。该DAO根据用户权限判断是否进行修改,删除文件等操作。
* 如果有足够的权限,则调用FileTblDaoImpl相关方法操作文件
*
*/

class FileTblDaoProxy implements FileTblDao {
    FileTblDao fileTblDao;
    Permission permission;
    
    public FileTblDaoProxy(Permission permission) {
        if (fileTblDao == null) {
            fileTblDao = new FileTblDaoImpl();
        }
        
        this.permission = permission;
    }
    
    public void deleteFile(FileTbl fileTbl) {
        if (Permission.PERMISSION.ALL.equals(permission.getLevel())) {
            fileTblDao.deleteFile(fileTbl);
        } else {
            System.out.println("no permission to delete file:" + fileTbl.getId());
        }
    }

    public void updateFile(FileTbl fileTbl) {
        
        if (Permission.PERMISSION.ALL.equals(permission.getLevel())) {
            fileTblDao.updateFile(fileTbl);
        } else {
            System.out.println("no permission to update file:" + fileTbl.getId());
        }
    }

    public void saveFile(FileTbl fileTbl) {
        if (Permission.PERMISSION.ALL.equals(permission.getLevel())) {
            fileTblDao.saveFile(fileTbl);
        } else {
            System.out.println("no permission to save file:" + fileTbl.getId());
        }
    }

    public FileTbl getFile(String fileId) {
        return fileTblDao.getFile(fileId);
    }
}


//文件表类
class FileTbl {
    private String id;

    public FileTbl(String id) {
        this.id = id;
    }
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
    
}

//权限控制类
class Permission {
    public static enum PERMISSION {
        ALL,
        SEARCH
    }
    
    private PERMISSION level;
    
    public Permission(PERMISSION level) {
        this.level = level;
    }

    public PERMISSION getLevel() {
        return level;
    }
}



执行Client,输出结果:
C:\Proxy>javac *.java
C:\Proxy>java Client
no permission to update file:file01
update file:file01
C:\Proxy>

Proxy模式与Adapter模式,Decorator模式,Builder模式等的区别
Proxy模式与其他几个构造型模式比如Adapter模式,Decorator模式等很相似,
设计模式之Adapter - 适配器模式
设计模式之Bridge - 桥接模式
设计模式之Decorator - 装饰模式
与Proxy模式一样,它们具有以下相同点:
- 都是构造型的设计模式
- 都是通过新类对原有类的封装(继承或委让的方式),即通过新类访问原有的类。
但它们不同点:
- 目的或行为结果不同:
    Proxy模式在客户端访问目标对象前或后,需要进行某些特别的处理;
    Adapter模式则纯粹为了给目标类或库等作一个封装,使其适合被新的系统使用,即Adapter模式是为了给目标类统一接口;
    Bridge模式则是为了分离事务内部具有并列属性的抽象与具体行为;
    Decorator模式则是可以在运行期动态地改变一个对象方法的行为。
- 接口的方式不同:
    Proxy模式中被代理的目标对象与Proxy类使用同一个接口;
    Adapter模式是为调用原对象而准备一个新的接口;
    Bridge模式中的抽象与具体行为分别使用2个不同的接口。
    Decorator模式除了装饰(Decorator)类与被装饰的类使用同一个接口之外,装饰(Decorator)类的实现还使用委让的方式。

在实际的应用中,根据我们的目的的不同而选用不同的设计模式。
分享到:
评论

相关推荐

    Proxy-SwitchyOmega-Chromium-2.5.15.zip

    Proxy-SwitchyOmega是一款强大的网络代理管理插件,专为Chromium浏览器(Chromium是Google Chrome浏览器的基础开源版本)设计。这款插件允许用户在不同的网络环境之间快速切换,包括HTTP、HTTPS、SOCKS4、SOCKS5等...

    java设计模式视频教程-代理模式.rar

    在这个“java设计模式视频教程-代理模式.rar”压缩包中,包含了一部关于代理模式的视频教程,以及相关的课件和示例代码。 代理模式的核心思想是通过代理类来代理原始对象,为原始对象提供一个替代品或占位符,以...

    apache开源项目源码commons-proxy-1.0-src(全部高质量代理模式proxy的java源程序)

    java.proxy,代理模式源码,设计模式,apache开源项目源码commons-proxy-1.0-src 各种代理模式操作的工具类源码以及代理模式案例源码,你会从中得到意想不到的效果! apache开源组织开发的开源项目源码,其优良的代码...

    设计模式C++学习之代理模式(Proxy)

    代理模式是一种设计模式,它是结构型模式之一,主要用于在客户端和目标对象之间建立一个代理对象,以便控制对目标对象的访问。在C++中,代理模式可以用来为其他对象提供一种代理以控制对这个对象的访问,或者增加...

    设计模式精解-GoF-23种设计模式解析--附C++源代码

    - 代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。 - 外观模式(Facade):提供一个统一的接口,用来访问子系统的一组接口。 - 适配器模式(Adapter):使两个接口不兼容的类能够协同工作。 ...

    设计模式--代理模式

    代理模式是一种常用的设计模式,它在软件开发中扮演着重要角色,允许我们通过一个代理类来控制对原对象的访问。在《设计模式:可复用面向对象软件的基础》(通常称为GoF设计模式)中,代理模式被定义为“为其他对象...

    设计模式之代理模式proxy

    **设计模式之代理模式(Proxy Pattern)** 设计模式是软件工程中的一种最佳实践,它是在特定情境下解决常见问题的模板。代理模式是其中一种行为设计模式,它的核心思想是为一个对象提供一个替身或者代理,以控制对...

    charles-proxy-4.6.4-win64安装包

    Charles 是一款强大的网络代理软件,尤其在 IT 领域,它是开发者和网络调试人员的必备工具之一。这个“charles-proxy-4.6.4-win64”安装包是专为 Windows 64 位系统设计的最新版本,用于帮助用户捕获、查看并分析...

    java设计模式---诙谐易懂版

    例如,代理模式(Proxy Pattern)、单例模式(Singleton Pattern)、工厂方法模式(Factory Method Pattern)、抽象工厂模式(Abstract Factory Pattern)、适配器模式(Adapter Pattern)、模板方法模式(Template ...

    代理模式 proxy-learn.rar

    代理模式是一种设计模式,它允许我们在不修改原有对象的情况下,为对象添加额外的功能或控制访问。在Java中,代理模式有静态代理和动态代理两种主要实现方式,它们都是为了在客户端与目标对象之间插入一个代理对象,...

    c++-设计模式之代理模式(Proxy)

    代理模式(Proxy Pattern)是一种结构型设计模式,用于为其他对象提供一种代理以控制对这个对象的访问。代理模式通常用于保护、延迟加载、记录请求等场景,可以在不改变原有对象的情况下为其增加新的功能。 代理...

    设计模式之代理模式proxy.zip

    代理模式是一种常用的设计模式,它在软件开发中扮演着重要的角色。代理模式允许我们为一个对象创建一个代理,这个代理对象在客户端和目标对象之间起到中介的作用,可以增强或控制对目标对象的访问。代理模式的主要...

    设计模式课程设计---使用5个以上不同的设计模式完成(java)

    在本设计模式课程设计中,我们重点探讨了五个核心的设计模式:原型模式、单例模式、抽象工厂模式、代理模式和建造者模式。这些模式在Java编程中具有广泛的应用,能够帮助开发者创建更加灵活、可扩展和易于维护的代码...

    设计模式之代理模式Proxy

    代理模式是设计模式中的一种结构型模式,它在对象交互中起到了中介的作用,允许通过代理对象来控制对原对象的访问。代理模式的核心思想是为一个对象提供一个替身,以便增加新的功能或者控制对原对象的访问。这种模式...

    设计模式-代理模式

    描述中提到的“重写了方法签名”,这是代理模式的一个关键步骤,通过定义代理协议(Protocol),并让目标对象(Target)和代理对象(Proxy)遵循这个协议,代理对象可以实现目标对象的方法,但可以添加额外的行为...

    Java设计模式-代理模式例子

    在这个“Java设计模式-代理模式例子”中,我们可能能看到如何创建静态代理类,以及如何利用`Proxy`和`InvocationHandler`创建动态代理。源码分析可以帮助我们更好地理解代理模式的实现细节,并能将其运用到自己的...

    26种设计模式-----pdf

    结构型模式则关注如何将类或对象组合成更大的结构,例如适配器模式(Adapter)、装饰器模式(Decorator)、代理模式(Proxy)、桥接模式(Bridge)和组合模式(Composite)。这些模式可以帮助我们处理类与类之间的...

    dynamic-proxy-demo.zip

    动态代理和静态代理是软件设计模式中的两种重要概念,它们主要应用于对象的增强或扩展,以便在不修改原有代码的情况下,增加新的功能或控制对象的行为。在这个“dynamic-proxy-demo.zip”压缩包中,我们可能找到了...

    设计模式PPT---25种设计模式详解

    7. 代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。 行为型模式则关注对象之间的交互和责任分配,包括: 1. 责任链模式(Chain of Responsibility):将请求沿着处理者链传递,直到某个处理者...

    设计模式专题之(六)代理模式---设计模式代理模式示例代码(python--c++)

    代理模式是一种常用的设计模式,它在软件开发中扮演着重要角色,主要用来为其他对象提供一种代理以控制对这个对象的访问。在这个专题中,我们将深入探讨代理模式,并通过Python和C++两种语言来实现示例代码。 首先...

Global site tag (gtag.js) - Google Analytics