代理模式简述
代理模式(Proxy Pattern)是程序设计中的一种设计模式。
所谓的代理可以简单理解为是一个中介。举一个生活中常见的例子:假如小王需要请刘德华唱歌,但是小王自己联系不到刘德华本人,小王只能联系他的经纪人,那么这个经纪人就是刘德华的代理。
在编程世界中,这个[代理者]就是一个类。这个类可以作为其它行为的接口。
代理模式的[统一建模语言(UML)
代理的分类
什么是静态代理
静态代理是代理模式的一种实现方式,它具有以下几个特点:
- 目标对象和代理对象实现的是同一个业务接口。UML 图中的 Proxy 类就是代理对象, RealSubject 类就是目标对象
- 目标对象必须实现接口。UML 图中的 Proxy 实现了接口 Subject
- 代理对象在程序的运行之前已经存在
- 能够做到对目标对象的灵活切换,但是无法完成功能的灵活切换
业务实现
唱歌。小王需要请刘德华唱歌,刘德华就是目标对象。
经纪人。经纪人就是代理对象。这个经纪人既可以跟小王对接,也可以跟车的刘德华对接。
小王,就是所谓的客户端。UML 中的 Client。
代码实现
- 定义买车的业务接口 Service
1 | void buyCar(); |
- 目标对象 LiuDeHua
1 | void buyCar(){ |
- 定义代理对象Agent并实现与目标对象一样的接口;并实现买车动作前后需要完成的动作
1 | void buyCar(){ |
- 测试
1 | public static void main(String[] args) { |
琢磨下:上述例子中,我们只能代理刘德华,那如果来了陈奕迅我们应该怎么办呢?
面向接口编程
类中的成员变量设计为接口,方法的形参设计为接口,方法的返回值设计为接口,调用时接口指向实现类
首先,在上面的例子中,我们的代理类 Agent在自己的类中new了一个 LiuDeHua的实例,然后完成了唱歌前的定价动作和唱歌后的结账动作。那么,这时候我们只能听到刘德华唱的歌。那如果我们现在想要听陈奕迅的歌,应该怎么办呢?难道在 Agent 中在 new 一个 ChenYiXun 的实例吗?我们的代理类(经纪人)每次只能代理一个实例(明星)啊。这时候,我们就要采用面向接口编程的方式了。
- 我们已经知道有一个接口 Service中有 sing()方法。那么接下来我们将Service 作为Agent 类的成员变量
1 | public class Agent implements Service { |
- 我们实现一个带有参数的构造方法:将 Service 作为参数传进去
1 | public class Agent implements Service { |
- 最后,我们将调用的方法,由直接 new 实现类改为接口指向
1 | public class Agent implements Service { |
MyTest 类中的代码:
- 第一版;此时 new Agent()调用的是无参构造
1 | public static void main(String[] args) { |
- 第二版;new Agent(Service target)调用的是参数为 Service 接口的有参构造;此时,会调用 Agent 的有参构造方法
public Agent(Service target) {this.target = target;}
此时做到了接口指向实现类的动作
1 | public static void main(String[] args) { |
至此,我们实现了一个简单的静态代理,简单了解了面向接口编程的思想。