## 引入
在閻宏博士的《JAVA與模式》一書中開頭是這樣描述代理(Proxy)模式的:
> 代理模式是對象的結構模式。代理模式給某一個對象提供一個代理對象,并由代理對象控制對原對象的引用。
在我們實際生活中代理情況無處不在!你在淘寶上面買東西,你使用支付寶平臺支付,賣家請物流公司發貨、你請朋友幫你拿包裹,在這個過程匯總支付寶、物流公司、你朋友都扮演者“第三者”的角色在幫你完成物品的購買,這里的第三者我們可以將其稱之為代理者。
所謂代理就通過引用一個新的對象來實現對真實對象的操作或者將新的對象當做真實對象的一個替身,這種實現的機制就是代理模式,通過引用代理對象來訪問真實對象就是代理模式的設計動機。
## 定義
代理模式就是給一個對象提供一個代理,并由代理對象控制對原對象的引用。
在代理模式中,“第三者”代理主要是起到一個中介的作用,它連接客戶端和目標對象。
## 結構
所謂代理,就是一個人或者機構代表另一個人或者機構采取行動。在一些情況下,一個客戶不想或者不能夠直接引用一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。
代理模式類圖如下:

在代理模式中的角色:
● 抽象對象角色:聲明了目標對象和代理對象的共同接口,這樣一來在任何可以使用目標對象的地方都可以使用代理對象。
● 真實對象角色:它代表著真實對象,是我們最終要引用的對象。
● 代理對象角色:代理對象內部含有目標對象的引用,從而可以在任何時候操作目標對象;代理對象提供一個與目標對象相同的接口,以便可以在任何時候替代目標對象。代理對象通常在客戶端調用傳遞給目標對象之前或之后,執行某個操作,而不是單純地將調用傳遞給目標對象。
## 代碼實現
**例子一**
讀大學的時候都追過女生吧!某天你看到一位美女,一見鐘情,心里發誓要她做你女朋友。但是你想這樣直接上去可能會唐突了。于是你采用迂回政策,先和她室友搞好關系,然后通過她室友給她禮物。
抽象主題,送禮物接口:GiveGift.java
~~~
public interface GiveGift {
/**
* 送花
*/
void giveFlowers();
/**
* 送巧克力
*/
void giveChocolate();
/**
* 送書
*/
void giveBook();
}
~~~
你小子:You.java
~~~
public class You implements GiveGift {
BeautifulGirl mm ; //美女
public You(BeautifulGirl mm){
this.mm = mm;
}
public void giveBook() {
System.out.println(mm.getName() +",送你一本書....");
}
public void giveChocolate() {
System.out.println(mm.getName() + ",送你一盒巧克力....");
}
public void giveFlowers() {
System.out.println(mm.getName() + ",送你一束花....");
}
}
~~~
她閨蜜室友:HerChum.java
~~~
public class HerChum implements GiveGift{
You you;
public HerChum(BeautifulGirl mm){
you = new You(mm);
}
public void giveBook() {
you.giveBook();
}
public void giveChocolate() {
you.giveChocolate();
}
public void giveFlowers() {
you.giveFlowers();
}
}
~~~
美女一枚:BeautifulGirl.java
~~~
public class BeautifulGirl {
String name;
public BeautifulGirl(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
~~~
客戶端:Client.java
~~~
public class Client {
public static void main(String[] args) {
BeautifulGirl mm = new BeautifulGirl("小屁孩...");
HerChum chum = new HerChum(mm);
chum.giveBook();
chum.giveChocolate();
chum.giveFlowers();
}
}
~~~
**例子二**
客戶想要找房子,但是自己對周圍的房價或者房源不怎么了解,所以想要通過中介來代理.使用代理模式完成這個場景。
共同的接口
~~~
public interface Home {
public void selectHome();
}
~~~
客戶類
~~~
public class Custom implements Home {
@Override
public void selectHome() {
System.out.println("選擇房子!!!");
}
}
~~~
中介類
~~~
public class Intermediary implements Home {
private Custom custom;
public Intermediary(){
this.custom = new Custom();
}
@Override
public void selectHome() {
before();
custom.selectHome();
after();
}
private void before(){
System.out.println("中介找房源");
}
private void after(){
System.out.println("簽合同");
}
}
~~~
測試類
~~~
public class ProxyTest {
public static void main(String[] args) {
Home home = new Intermediary();
home.selectHome();
}
}
~~~
## 裝飾器模式和代理模式的區別
**裝飾器模式**
* 裝飾器類和被裝飾類實現同一個接口.
* 裝飾器類關注于在一個對象上動態的添加方法.
* 強調:增強方法
**代理模式**
* 代理類和真實處理類實現同一個接口.
* 代理模式關注于控制對對象的訪問,代理類通過代理模式向訪問他的客戶隱藏了真實調用的對象.
* 強調:增強
使用代理模式,代理和真實對象之間的關系在編譯時就已經確定了,而裝飾器者能夠在運行時遞歸的被構造.(代理模式會在代理類中創建真實處理類的一個實例,所以可以確定代理和真實對象的關系,而裝飾器模式是將原始對象作為一個參數傳給裝飾器類)
## 優點
* 1、職責清晰,真實角色就是實現實際的業務邏輯,不用擔心其它非本職責的事務,通過后期的代理完成一件完成事務,附帶的結果就是編程簡介清晰。在一定程度上降低了系統的耦合度。
* 2、代理對象可以在客戶端和目標對象之間起到中介的作用,這樣起到了中介的作用和保護了目標對象的作用.
* 3、高擴展性
## 缺點
* 1、由于在客戶端和真實主題之間增加了代理對象,因此有些類型的代理模式可能會造成請求的處理速度變慢。
* 2、 實現代理模式需要額外的工作,有些代理模式的實現非常復雜。
## 適用場景
* 1、 遠程代理:為一個對象在不同的地址空間提供局部代表。這樣可以隱藏一個對象存在于不同地址空間的事實。
* 2、 虛擬代理:通過使用過一個小的對象代理一個大對象。這樣就可以減少系統的開銷。
* 3、 保護代理:用來控制對真實對象的訪問權限。
## 總結
* 1、代理模式是通過使用引用代理對象來訪問真實對象,在這里代理對象充當用于連接客戶端和真實對象的中介者。
* 2、代理模式主要用于遠程代理、虛擬代理和保護代理。其中保護代理可以進行訪問權限控制。
- java
- 設計模式
- 設計模式總覽
- 設計原則
- 工廠方法模式
- 抽象工廠模式
- 單例模式
- 建造者模式
- 原型模式
- 適配器模式
- 裝飾者模式
- 代理模式
- 外觀模式
- 橋接模式
- 組合模式
- 享元模式
- 策略模式
- 模板方法模式
- 觀察者模式
- 迭代子模式
- 責任鏈模式
- 命令模式
- 備忘錄模式
- 狀態模式
- 訪問者模式
- 中介者模式
- 解釋器模式
- 附錄
- JVM相關
- JVM內存結構
- Java虛擬機的內存組成以及堆內存介紹
- Java堆和棧
- 附錄-數據結構的堆棧和內存分配的堆區棧區的區別
- Java內存之Java 堆
- Java內存之虛擬機和內存區域概述
- Java 內存之方法區和運行時常量池
- Java 內存之直接內存(堆外內存)
- JAVA內存模型
- Java內存模型介紹
- 內存模型如何解決緩存一致性問題
- 深入理解Java內存模型——基礎
- 深入理解Java內存模型——重排序
- 深入理解Java內存模型——順序一致性
- 深入理解Java內存模型——volatile
- 深入理解Java內存模型——鎖
- 深入理解Java內存模型——final
- 深入理解Java內存模型——總結
- 內存可見性
- JAVA對象模型
- JVM內存結構 VS Java內存模型 VS Java對象模型
- Java的對象模型
- Java的對象頭
- HotSpot虛擬機
- HotSpot虛擬機對象探秘
- 深入分析Java的編譯原理
- Java虛擬機的鎖優化技術
- 對象和數組并不是都在堆上分配內存的
- 垃圾回收
- JVM內存管理及垃圾回收
- JVM 垃圾回收器工作原理及使用實例介紹
- JVM內存回收理論與實現(對象存活的判定)
- JVM參數及調優
- CMS GC日志分析
- JVM實用參數(一)JVM類型以及編譯器模式
- JVM實用參數(二)參數分類和即時(JIT)編譯器診斷
- JVM實用參數(三)打印所有XX參數及值
- JVM實用參數(四)內存調優
- JVM實用參數(五)新生代垃圾回收
- JVM實用參數(六) 吞吐量收集器
- JVM實用參數(七)CMS收集器
- JVM實用參數(八)GC日志
- Java性能調優原則
- JVM 優化經驗總結
- 面試題整理
- 面試題1
- java日志規約
- Spring安全
- OAtuth2.0簡介
- Spring Session 簡介(一)
- Spring Session 簡介(二)
- Spring Session 簡介(三)
- Spring Security 簡介(一)
- Spring Security 簡介(二)
- Spring Security 簡介(三)
- Spring Security 簡介(四)
- Spring Security 簡介(五)
- Spring Security Oauth2 (一)
- Spring Security Oauth2 (二)
- Spring Security Oauth2 (三)
- SpringBoot
- Shiro
- Shiro和Spring Security對比
- Shiro簡介
- Session、Cookie和Cache
- Web Socket
- Spring WebFlux