代理模式
代理模式:为其他对象提供一种代理,以控制这个对象的访问。翻译一下。。。通过代理的方式,代理其他的对象,以便控制这个对象的访问。
举栗子
先把定义放在那,先不要管它到底说了个啥,先来举个服务器的例子。
大家都应该使用过云服务器,有了云服务器,我们只需要通过任何一台终端就可以访问服务器,把命令发给服务器,服务器处理相关命令。
interface Computer {
void command(String command);
}
class Server implements Computer{
public void command(String command) {
System.out.println("服务器调用" + command);
}
}
class Terminal implements Computer{
private Computer server = null;
public void connectServer(Computer server) {
this.server = server;
System.out.println("连接服务器成功");
}
public void command(String command) {
if(this.server == null)
System.out.println("请先连接服务器");
else
server.command(command);
}
}
public class Client {
public static void main(String[] args) {
//创建终端
Computer terminal = new Terminal();
//创建服务器
Computer server = new Server();
//连接服务器
((Terminal)terminal).connectServer(server);
//发送命令
terminal.command("ls");
}
}
类图:
可以看到,对于客户端来说,它只是发送命令,最终执行命令的是是服务器。这就是代理模式;在回头看定义:为其他对象其他对象:服务器提供一种代理代理:客户端,以控制这个对象的访问代理控制服务器的访问。
代理模式的类图如下:
代理模式主要有三个角色:
1. Subject : 抽象主题接口,一个业务需求的接口。
2. RealSubject : 被代理的角色,业务逻辑的具体执行者
3. Proxy : 代理角色,应用被代理的角色,把所有的抽象主题顶一个的方法限制委托给真实角色。
代理类有自己的个性
代理类应该有个性,如果和被代理类一样,设置代理就没什么意义了。因此,代理类在调用被代理角色的方法时,可以添加一些限制,还可以在调用被代理角色的方法之前(后),进行其他的操作。如下
class Proxy implements Subject {
Subject realSubject;
//代理类的“个性”
private void before(){
...
}
private void after(){
...
}
//代理类调用被代理角色的方法之前(后),可以有其他的操作
public void doSomething(){
this.before();
this.realSubject.doSomething();
this.after();
}
}
代理类除了是主题接口的子类外,还可以是其他接口的子类。
应用场景
在第一开始学习的时候,我觉得这个代理模式就是"多此一举",其实并不是这样的,上面服务器、终端的例子,并没有体现出来代理角色的限制委托。对于真实角色而言,它关注的更多的应该是业务处理的逻辑,对于具体的业务(除了处理的逻辑,还包括其他操作),则可通过代理模式完成。
优点
- 职责清晰,被代理的的角色,不用关心职责之外的事务,被代理的角色符合单一职责原则。对于事务的完成,则交给代理。
- 高扩展性,只要主题接口不发生变化,修改真实主题角色(被代理的角色),代理角色不需要修改,而上层使用的是代理,所以上层的调用也不用修改。