Home [閱讀筆記][Design Pattern] Ch7.代理模式 Proxy
Post
Cancel

[閱讀筆記][Design Pattern] Ch7.代理模式 Proxy

代理模式 Proxy

代理模式(Proxy):為其他物件提供一種代理以控制對這個物件的存取。

代理模式其實就是在存取物件時引入一定程度的間接性,因為這種間接性,可以附加多種用途。

說白了,代理就是真實物件的代表。

代理模式 Proxys結構

  • Subject 類別:定義了RealSubjectProxy共用介面,這樣就在任何使用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 類別

定義了RealSubjectProxy共用介面,這樣就在任何使用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. 遠端代理
  2. 虛擬代理
  3. 安全代理
  4. 智慧參考

1.遠端代理

遠端代理,也就是為一個物件在不同的位址空間提供局部代表。這樣可以隱藏一個物件存在於不同位址空間的事實。

比如WebService.Net中的應用,當我在應用程式的專案中加入一個Web參考,參考一個WebService,此時會在專案中產生一個WebReference的資料夾和一些檔案,其實他們就是代理,這就使得用戶端程式調用代理就可以解決遠端存取的問題。

2.虛擬代理

虛擬代理,是根據需要建立消耗很大的物件。透過它來存放實體化需要很長時間的真實物件。這樣就可以達到性能的最佳化。

比如說在瀏覽一個很大的HTML網頁時,裡面可能有很多的文字和圖片,但你還是可以很快看到頁面,此時你所看到的是所有的文字,但圖片卻是一張一張地下載後才能看到。那些未顯示的圖框,就是透過虛擬代理來替代了真實的圖片,此時代理儲存了真實圖片的路徑和尺寸。

瀏覽器當中是用代理模式來優化下載的。

3.安全代理

安全代理,用來控制真實物件存取時的許可權。一般用於物件應該有不同的存取許可權的時候。

4.智慧參考

智慧參考,是指當調用實的物件時,代理處理另外一些事。

例如:

  • 計算真實物件的參考次數,當該物件沒有參考時,可以自動釋放它,
  • 或當第一次參考一個持久物件時,將它裝入記憶體;
  • 或在存取一個實際物件前,檢查是否已經鎖定它,以確保其他物件不能改變它。
    它們都是透過代理在存取一個物件時附加一些內務處理。

代理模式其實就是在存取物件時引入一定程度的間接性,因為這種間接性,可以附加多種用途。

說白了,代理就是真實物件的代表。

This post is licensed under CC BY 4.0 by the author.

[閱讀筆記][Design Pattern] Ch6.裝飾模式 Decorator

[閱讀筆記][Design Pattern] Ch8.工廠方法模式 Factory Method