设计模式——代理模式
代理模式(Proxy Pattern)是一个使用率非常高的模式。
定义: Provide a surrogate or placeholder for another object to control access to it. (为其对象提供一种代理以控制这个对象的访问)
代理模式也叫委托模式,它是一项基本的设计技巧。许多其他的模式,如状态模式、策略模式、访问者模式本质上是在更特殊的场合采用了委托模式,而且在日常应用中,代理模式可以提供非常好的访问控制。
三个角色的定义
抽象主题类可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要求。
也叫做被委托的角色、被代理的角色。是业务逻辑的具体执行者。
也叫委托类、代理类。它负责对真实角色的应用,把所以抽象主题定义的方法限制委托给真实主题角色实现,并且在真实主题角色处理完毕前后做预处理和善后工作。
一个代理类可以代理多个被委托者或者被代理者,因此一个代理者具体代理哪个真实主题角色,是由场景类决定的。在通常情况下,一个接口只需要一个代理类就可以了,具体代理哪个实现类由高层模块决定,也就是在代理类的构造函数中传递被代理者。
类似现实生活中买房子的中介,打官司的律师。你不想参与中间过程的是是非非。减轻用户的负担。代理模式使用场景非常多。最典型的是Spring AOP中的动态代理。
普通代理就是我们要知道代理的存在,也就是类似GamePlayerProxy这个代理类的存在,然后才能访问。
普通代理的要求就是客户端只能访问代理角色,而不能访问真实角色。以游戏代练为例子,
GamePlayer的构造函数增加了_gamePlayer参数,而代理角色则只要传入代理者名字即可,而不需要说是替哪个对象做代理
在构造函数中,传来进来一个IGaemPlayer对象,检查谁能创建真实的角色,或者做出别的限制。
仅仅修改了构造函数,传递进来一个代理者名称,即可进行代理,在这种改造下,系统更加简洁,调用者只知道代理的存在就行,不用知道代理了谁。
在该模式下,调用者只知道代理而不知道真实的角色是谁,屏蔽了真实角色的变更对高层模块的影响,真实的主题角色想怎么修改都可以,对高层次的模块没有任何的影响,只要你实现了接口所对应的方法,该模式非常适合对扩展性要求较高的场合。
强制代理是要“强制”,必须通过真实角色查找到代理角色,否则不能进行访问。无论是通过代理类还是直接new一个主题角色类,都不能访问,只有通过真实角色指定的代理类才能访问,也就是说由真实的角色管理代理角色。例如你和一个明星比较熟,你直接找明星帮忙要见导演,但是明星说她比较忙,让你找她的经纪人。你本来想绕过她的代理,谁知道她返回的还是她的代理,这就是强制代理。你可以不知道代理的存在,但是你的所作所为还是需要代理为你提供服务。
强制代理的概念就是要从真实的角色查找到代理角色,不允许直接访问真实角色。高层模块只要调用 getProxy() 就可以访问真实角色的所以方法,它根本不需要产生一个代理出来,代理的管理已经由真实角色自己完成。
一个类可以实现多个接口,完成不同任务的整合。也就是说代理类不仅仅可以实现主题接口,也可以实现其他接口完成不同的任务,而且代理的目的是在目标对象方法的基础上作增强,这种增强的本质通常就是对目标对象的方法进行拦截合过滤。
动态代理
代理模式通常用于以下情况:
- 远程代理:控制远程对象的访问
- 虚拟代理:控制对实际对象的访问,如延迟加载等
- 保护代理:控制对对象的访问权限
- 缓存代理:对频繁访问的对象进行缓存,提高性能
代理模式的核心思想是将原始对象封装在代理对象中,客户端无需知道原始对象的真实实现,只需要与代理对象交互即可。
代理模式的优点是:
- 增加了对象的间接性,降低了系统的耦合度
- 可以在不改变原始对象的情况下对其进行控制和扩展
- 提高了系统的性能,特别是对频繁的对象访问进行了缓存
常见的代理模式包括静态代理和动态代理两种。静态代理需要为每个原始对象定义一个代理对象,而动态代理可以在运行时为任意实现了某个接口的对象生成代理对象。
总之,代理模式是一种非常常用的设计模式,可以在很多场合中发挥作用,例如网络代理、安全代理、缓存代理等。