Zer0e's Blog

设计模式之代理模式

字数统计: 977阅读时长: 3 min
2020/08/10 Share

前言

今天来讲讲结构型模式的一种——代理模式。

正文

概念与介绍

代理模式其实在日常生活中的例子很多,比如买东西的时候,代售点就是代理模式的一种,再比如代理上网,这个对许多人并不陌生,这里就不再多说(小声)。
那代理模式的主要意图就是由于访问目标有种种困难或问题,或者说无法访问,只有通过另一个对象才能访问这个对象,那这种模式就称作代理模式。
代理模式常用的场景有:

  • 无法直接访问对象
  • 访问对象有困难
  • 不想直接访问对象,想在中间做控制

通常在这些需求下,通过代理模式,来间接访问对象。

实现

我们用实际例子来实现代理模式。
由于新发售的游戏只在日本本土上架,要购买这款游戏必须通过代购入手。
代购(代理对象)代替我(真实对象)去买游戏(间接访问的操作)
首先,我们创建对象接口(Subject),不管是真实对象,还是代理对象都会实现这个接口。

1
2
3
public interface Subject {
public void buyGameFromJapan();
}

其次我们创建真实对象,即”我”:

1
2
3
4
5
6
public class RealSubject implements Subject{
@Override
public void buyGameFromJapan() {
System.out.println("买了一部游戏");
}
}

创建代理对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Proxy implements Subject{
@Override
public void buyGameFromJapan() {
RealSubject realSubject = new RealSubject();
realSubject.buyGameFromJapan();
this.doOtherThing();
}


public void doOtherThing(){
// 记录购买的时间
System.out.println("购买时间为:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(System.currentTimeMillis()));
}
}

最后客户端调用

1
2
3
4
5
6
7
8
9
10
11
public class Client {
public static void main(String[] args) {
Proxy proxy = new Proxy();
proxy.buyGameFromJapan();
}
}

/*
买了一部游戏
购买时间为:2020-08-10 16:13:31
*/

以上我们通过一个例子实现了代理模式,代理模式与之前的观察者模式类似,对象在初始化时,可以选择隐式初始化,即我们在Proxy中初始化了一个RealSubject,又可以在客户端中初始化realSubject,传进Proxy。两种方式都可以。
那有些同学就好奇,这么做有啥意义,我直接在自己realSubject中自己写一个方法调用不就好了吗?其实不然,如果有许多的委托类,每个类的方法都不一样,那么就需要我去内部查看调用方法,而代理模式就是为了让客户端无需关心对象内部的具体实现内容,而是交给代理类去实现,从而屏蔽不同委托类之间的差异。
其实简单来说,就是让客户端只关心调用,而不关心怎么实现。

优缺点

代理模式的优点前面也提到过,即协调了调用者和被调用者,有效地降低系统耦合度。其次,代理位于客户端与目标对象中间,可以保护对象,并增加具体操作。
缺点则是由于增加了一层代理,访问速度可能受到影响。其次是去实现代理模式可能会较为复杂。

应用场景

代理模式应用场景很多,主要有:

  • 保护原始对象,根据用户不同提供不同权限。
  • 降低对象大小,使用小对象代理大对象,减少系统开销。
  • 访问远程对象,由于远程对象实现逻辑不同,需要代理来协商。
  • 需要额外操作,在操作对象时,需要额外操作,例如记录日志等。

后话

本文从一个例子讲解了代理模式的实现,以及代理模式常用场景,顺带一提,Spring AOP中也使用了代理模式,如果有时间的话,后续会继续谈谈Spring AOP中的代理。

CATALOG
  1. 1. 前言
  2. 2. 正文
    1. 2.1. 概念与介绍
    2. 2.2. 实现
    3. 2.3. 优缺点
    4. 2.4. 应用场景
  3. 3. 后话