定義:
Provide a surrogate or placeholder for another object to control access to it.
為其他對象一種代理以控制對這個對象的訪問。
一般描述:
一般包含的三個角色:抽象主題、具體主題、代理主題。
- 抽象主題:是一個抽象類或接口,是一個普通的業務類型定義。
- 具體主題:業務邏輯的具體執行者
- 代理角色:負責對真是角色的應用,把所有抽象主題類定義的方法限制委托給真實主題角色實現。
通用類圖:
通用代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
package Proxy; //抽象主題類: public interface Subject { public void doSomething(); } package Proxy; //具體主題類 public class RealSubject implements Subject{ @Override public void doSomething() { System.out.println( "業務邏輯..." ); } } package Proxy; //代理主題類 public class Proxy implements Subject{ private Subject sub = null ; @Override public void doSomething() { this .sub.doSomething(); } public Proxy(Subject sub){ this .sub = sub; } } package Proxy; //客戶端 public class Client { public static void main(String[] args) { Subject realsub = new RealSubject(); Subject proxy = new Proxy(realsub); proxy.doSomething(); } } |
優點:
1. 職責清晰
2. 高擴展
代理模式的擴展:
普通代理:
具體主題類對高層透明,在代理主題類中構造具體主題類
代碼實現:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
package GeneralProxy; public interface Subject { public void doSomething(); } package GeneralProxy; public class RealSubject implements Subject{ private String name = null ; @Override public void doSomething() { System.out.println( this .name + "被代理,正在執行業務邏輯..." ); } public RealSubject(Subject proxy,String name) throws Exception{ if (proxy == null ){ throw new Exception( "無法創建被代理對象" ); } else { this .name = name; } } } package GeneralProxy; public class Proxy implements Subject{ private Subject realsub = null ; public Proxy(String name) { try { realsub = new RealSubject( this , name); } catch (Exception e) { e.printStackTrace(); } } public void doSomething() { realsub.doSomething(); } } package GeneralProxy; public class Client { public static void main(String[] args) { //普通代理 Subject proxy = new Proxy( "張三" ); proxy.doSomethaing(); } } |
強制代理:
必須通過訪問具體主題類獲取代理主題類的對象,然后用代理主題類控制訪問
代碼實現:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
package MustProxy; public interface Subject { public void doSomething(); public Subject getProxy(); } package MustProxy; public class RealSubject implements Subject{ private String name = null ; private Subject proxy = null ; @Override public void doSomething() { if (isProxy()){ System.out.println( this .name + "被代理,正在執行業務邏輯..." ); } else { System.out.println( "請先訪問代理..." ); } } public RealSubject(String name) { this .name = name; } public Subject getProxy() { proxy = new Proxy( this ); return this .proxy; } private boolean isProxy(){ if ( this .proxy == null ){ return false ; } else { return true ; } } } package MustProxy; public class Proxy implements Subject{ private Subject realSub = null ; public Proxy(Subject realSub) { this .realSub = realSub; } public void doSomething() { this .realSub.doSomething(); } public Subject getProxy() { return this ; } } package MustProxy; public class Client { public static void main(String[] args) { Subject realSub = new RealSubject( "張三" ); realSub.doSomething(); Subject proxy = realSub.getProxy(); proxy.doSomething(); } } |
應用場景
現實世界中,秘書就相當于一個代理,老板開會,那么通知員工開會時間、布置會場、會后整理會場等等開會相關工作就可以交給秘書做,老板就只需要開會就行了,不需要親自做那些事。同理,在我們程序設計中也可使用代理模式來將由一系列無關邏輯組合在一起的代碼進行解耦合,比如業務代碼中的日志代碼就可以在代理中進行。Spring的AOP就是典型的動態代理應用。
代理模式的應用形式
(1)遠程代理(Remote Proxy) -可以隱藏一個對象存在于不同地址空間的事實。也使得客戶端可以訪問在遠程機器上的對象,遠程機器可能具有更好的計算性能與處理速度,可以快速響應并處理客戶端請求。
(2)虛擬代理(Virtual Proxy) – 允許內存開銷較大的對象在需要的時候創建。只有我們真正需要這個對象的時候才創建。
(3)寫入時復制代理(Copy-On-Write Proxy) – 用來控制對象的復制,方法是延遲對象的復制,直到客戶真的需要為止。是虛擬代理的一個變體。
(4)保護代理(Protection (Access)Proxy) – 為不同的客戶提供不同級別的目標對象訪問權限
(5)緩存代理(Cache Proxy) – 為開銷大的運算結果提供暫時存儲,它允許多個客戶共享結果,以減少計算或網絡延遲。
(6)防火墻代理(Firewall Proxy) – 控制網絡資源的訪問,保護主題免于惡意客戶的侵害。
(7)同步代理(SynchronizationProxy) – 在多線程的情況下為主題提供安全的訪問。
(8)智能引用代理(Smart ReferenceProxy) - 當一個對象被引用時,提供一些額外的操作,比如將對此對象調用的次數記錄下來等。
(9)復雜隱藏代理(Complexity HidingProxy) – 用來隱藏一個類的復雜集合的復雜度,并進行訪問控制。有時候也稱為外觀代理(Façade Proxy),這不難理解。復雜隱藏代理和外觀模式是不一樣的,因為代理控制訪問,而外觀模式是不一樣的,因為代理控制訪問,而外觀模式只提供另一組接口。