## 定义

```
给某一个对象提供一个代理对象，并由代理对象来控制对原对象的访问。 

```

## 设计的原则和思想

1.  解耦的是代理者与被代理者。
2.  不变部分是代理者，变化部分是被代理者。
3.  核心思想是在不改变对象的情况下，为对象增加一些与本身业务没什么关系的额外功能,但不会为对象本身的功能进行增强。

## 一句话概括设计模式

```
通过代理的方式去控制对一个对象的访问

```

## 结构中包含的角色

1.  Subject（抽象主题角色）
2.  Proxy（代理主题角色）
3.  RealSubject（真实主题角色）

## 最小可表达代码

```
interface Subject {
    public function request();
}

class RealSubject implements Subject 
{
    public function request()
    {
        echo '真实对象执行';
    }
}

class Proxy implements Subject
{
    private $realSubject;

    public function __construct()
    {  
        $this->realSubject = new RealSubject();
    }

    public function request() 
    {
        $this->realSubject->request();
    }
}

$proxy = new Proxy();
$proxy->request();

```

## 优点

1.  替换代理类不用修改代码。
2.  在调用者和被调用者之间增加了代理对象，降低了系统的耦合度。

## 缺点

1.  增加代理对象可能会对有些代理模式的请求的处理速度变慢，例如保护代理。
2.  有些代理模式实现代码比较复杂，例如远程代理。

## 何时使用

1.  限制、增强或修改某个对象的一些特性。
2.  无法直接访问某个对象或访问某个对象存在困难时时。
3.  为某个对象增加一些与本身业务没什么关系的额外功能时。
4.  需要延迟加载资源时。

### 实际应用场景

1.  监控
2.  缓存
3.  限流
4.  日志
5.  统计
6.  在12306买票。
7.  访问权限控制。
8.  通过中介去找房子。
9.  RPC框架,远程代理。
10. Spring AOP 动态代理。

### 静态代理和静态代理

```
静态 :  由我们编写的代理类。
动态 : 在程序运行时，通过反射机制动态生成。
```