介绍

Provide a surrogate or placeholder for another object to control access to it.(为其他对象提供一种代理以控制对这个对象的访问。 ) -设计模式之禅第2版

我的理解是,将非主要但又与业务流程相关的业务分给代理类处理。比如,顾客吃饭,要操心的是吃什么饭,怎么吃以及付钱。至于买菜,洗菜,做饭,盛饭,刷锅之类的事情,不需要顾客亲自动手

通用类图及通用代码

代理模式也有好多变种,这里先给一个完整的,其它的变种版本只看变化细节好了

完整

类图

代理模式 - 图1

代码

ISubject

  1. package cn.zjm404.stu.design.organization.proxy;
  2. public interface ISubject {
  3. public void method();
  4. }

Proxy

  1. package cn.zjm404.stu.design.organization.proxy;
  2. public class Proxy implements ISubject{
  3. private ISubject iSubject;
  4. public Proxy(ISubject _subject){
  5. this.iSubject = _subject;
  6. }
  7. @Override
  8. public void method() {
  9. //这边是代理角色组装的方法
  10. proxyMethod1();
  11. iSubject.method();
  12. }
  13. private void proxyMethod1(){
  14. //代理角色添加的方法
  15. }
  16. }

Subject

  1. package cn.zjm404.stu.design.organization.proxy;
  2. public class Subject implements ISubject{
  3. @Override
  4. public void method() {
  5. //写要完成的任务
  6. }
  7. }

Client

  1. package cn.zjm404.stu.design.organization.proxy;
  2. public class Client {
  3. public static void main(String[] args) {
  4. Proxy proxy = new Proxy(new Subject());
  5. proxy.method();
  6. }
  7. }

普通代理:只暴露代理类

也就是Proxy构造时,不传入被代理类对象了,在构造函数中实例化被代理类 代理模式 - 图2如果被代理类有属性的化,代理类的构造函数就传被代理类的属性就好

  1. package cn.zjm404.stu.design.organization.proxy;
  2. public class Proxy implements ISubject{
  3. private ISubject iSubject;
  4. public Proxy(){
  5. this.iSubject = new Subject;
  6. }
  7. @Override
  8. public void method() {
  9. //这边是代理角色组装的方法
  10. proxyMethod1();
  11. iSubject.method();
  12. }
  13. private void proxyMethod1(){
  14. //代理角色添加的方法
  15. }
  16. }

强制代理:指定代理类

被代理对象聚合指定的代理类,然后获取它。在执行前判断一下proxy是否为null来确定是否为指定的proxy

  1. package cn.zjm404.stu.design.organization.proxy;
  2. public class Subject implements ISubject{
  3. private Proxy proxy;
  4. @Override
  5. public void method() {
  6. if(!isProxy()){
  7. //抛出一个异常~
  8. }
  9. //写要完成的任务
  10. }
  11. public ISubject getProxy(){
  12. this.proxy = new Proxy(this);
  13. return this.proxy;
  14. }
  15. public boolean isProxy(){
  16. return this.proxy != null;
  17. }
  18. }

动态代理

介绍及类图

上面的代理有一个小问题,就是要代理的话,得和被代理类“成为兄弟”,这样,如果多个被代理类不是“亲戚”且数量较多的话,代理类就太多了。如果这些代理类的处理逻辑相同的话,那么可以使用动态代理来减少重复代码。简单来说就是消去 Proxy 与 ISubject 的关联
image.png
变成以下,避免 Proxy 与 ISubject 产生直接依赖,改为使用反射来实现 Object 到 Subject 的转换 代理模式 - 图4

代码