代理模式 Proxy
代理模式(Proxy):為其他物件提供一種代理以控制對這個物件的存取。
代理模式其實就是在存取物件時引入一定程度的間接性,因為這種間接性,可以附加多種用途。
說白了,代理就是真實物件的代表。
代理模式 Proxys結構
Subject類別:定義了RealSubject和Proxy共用介面,這樣就在任何使用RealSubject的地方都可以使用Proxy。RealSubject類別:定義Proxy所代表的真實實體Proxy類別:保存一個引用讓代理可以訪問實體,並提供一個與Subject介面相同的介面,這樣代表就可以用來替代實體。
1
2
3
4
5
6
7
8
9
10
11
Client
↓
Subject Subject類別,定義了RealSubject和Proxy共用介面,這樣就在任何使用RealSubject的地方都可以使用Proxy
+ Requst()
RealSubject:Subject RealSubject類別,定義Proxy所代表的真實實體
+ Requst()
Proxy:Subject Proxy類別,保存一個引用讓代理可以訪問實體,並提供一個與Subject介面相同的介面,這樣代表就可以用來替代實體
- realSubject
+ Requst()
Subject 類別
定義了RealSubject和Proxy共用介面,這樣就在任何使用RealSubject的地方都可以使用Proxy。
1
2
3
4
//Subject 類別:定義了RealSubject和Proxy共用介面,這樣就在任何使用RealSubject的地方都可以使用Proxy
abstract Subject {
public abstract void Request();
}
RealSubject 類別
定義Proxy所代表的真實實體
1
2
3
4
5
6
//RealSubject 類別: 定義Proxy所代表的真實實體
class RealSubject:Subject {
public override void Request() {
Console.WriteLine("真實的請求");
}
}
Proxy類別
保存一個引用讓代理可以訪問實體,並提供一個與Subject介面相同的介面,這樣代表就可以用來替代實體
1
2
3
4
5
6
7
8
9
//Proxy類別,保存一個引用讓代理可以訪問實體,並提供一個與Subject介面相同的介面,這樣代表就可以用來替代實體
class Proxy:Subject {
public override void Request() {
if(realSubject == null) {
realSubject = new RealSubject();
}
realSubject.Request();
}
}
用戶端
1
2
Proxy proxy = new Proxy();
proxy.Request();
沒有代理的程式碼
假如有一個男孩想追求一個女孩,但女孩不認識追求他的人,只認識追求者(男孩)的朋友。
女孩並不認識追求者,這樣的寫法就等於他們之間認識,並且是追求者親自送東西給女孩,這樣寫是有問題的。
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
Gril gril = new Gril();
gril.Name = "KiKi";
//此處會有問題,因為kiki不認識追求者
Pursuit pursuit = new Pursuit(gril);
pursuit.GiveDolls();
//追求者
class Pursuit {
Gril gril;
public Pursuit(Gril gril) {
this.gril = gril;
}
public void GiveDolls() {
Console.WriteLine($"{gril.Name},送妳洋娃娃");
}
public void GiveFlower() {
Console.WriteLine($"{gril.Name},送妳鮮花");
}
public void GiveChocolate() {
Console.WriteLine($"{gril.Name},送妳巧克力");
}
}
//被追求者
class Gril {
public string Name{ get; set;}
}
代理模式的程式碼
代理介面
定義追求者和追求者朋友的共用介面。
1
2
3
4
5
interface IGive {
void GiveDolls();
void GiveFlower();
void GiveChocolate();
}
追求者類別
讓「追求者」去實現「送禮物」的介面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Pursuit: IGive {
Gril gril;
public Pursuit(Gril gril) {
this.gril = gril;
}
public void GiveDolls() {
Console.WriteLine($"{gril.Name},送妳洋娃娃");
}
public void GiveFlower() {
Console.WriteLine($"{gril.Name},送妳鮮花");
}
public void GiveChocolate() {
Console.WriteLine($"{gril.Name},送妳巧克力");
}
}
代理類別
讓「代理」也去實現「送禮物」的介面,在實現方法中去呼叫「追求者」類別的相關方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Proxy:IGive {
Pursuit pursuit;
public Proxy(Gril gril) {
this.pursuit = new Pursuit(gril);
}
//在實現方法中去呼叫「追求者」類別的相關方法
public void GiveDolls() {
pursuit.GiveDolls();
}
public void GiveFlower() {
pursuit.GiveFlower();
}
public void GiveChocolate() {
pursuit.GiveChocolate();
}
}
用戶端
1
2
3
4
5
6
7
8
9
10
11
12
13
Gril gril = new Gril();
gril.Name = "KiKi";
Proxy proxy = new Proxy(gril);
proxy.GiveDolls();
proxy.GiveFlower();
proxy.GiveChocolate();
//輸出:
//KiKi,送妳洋娃娃
//KiKi,送妳鮮花
//KiKi,送妳巧克力
代理模式 Proxy應用
代理模式都用在一些什麼場合呢?
- 遠端代理
- 虛擬代理
- 安全代理
- 智慧參考
1.遠端代理
遠端代理,也就是為一個物件在不同的位址空間提供局部代表。這樣可以隱藏一個物件存在於不同位址空間的事實。
比如WebService在.Net中的應用,當我在應用程式的專案中加入一個Web參考,參考一個WebService,此時會在專案中產生一個WebReference的資料夾和一些檔案,其實他們就是代理,這就使得用戶端程式調用代理就可以解決遠端存取的問題。
2.虛擬代理
虛擬代理,是根據需要建立消耗很大的物件。透過它來存放實體化需要很長時間的真實物件。這樣就可以達到性能的最佳化。
比如說在瀏覽一個很大的HTML網頁時,裡面可能有很多的文字和圖片,但你還是可以很快看到頁面,此時你所看到的是所有的文字,但圖片卻是一張一張地下載後才能看到。那些未顯示的圖框,就是透過虛擬代理來替代了真實的圖片,此時代理儲存了真實圖片的路徑和尺寸。
瀏覽器當中是用代理模式來優化下載的。
3.安全代理
安全代理,用來控制真實物件存取時的許可權。一般用於物件應該有不同的存取許可權的時候。
4.智慧參考
智慧參考,是指當調用實的物件時,代理處理另外一些事。
例如:
- 計算真實物件的參考次數,當該物件沒有參考時,可以自動釋放它,
- 或當第一次參考一個持久物件時,將它裝入記憶體;
- 或在存取一個實際物件前,檢查是否已經鎖定它,以確保其他物件不能改變它。
它們都是透過代理在存取一個物件時附加一些內務處理。
代理模式其實就是在存取物件時引入一定程度的間接性,因為這種間接性,可以附加多種用途。
說白了,代理就是真實物件的代表。