PHP的代理模式


代理模式與父類和接口的異同

  • 相同點:代理模式的作用和父類以及接口和組合的作用類似,都是為了聚合共用部分,減少公共部分的代碼
  • 不同點:
    • 相比起父類,他們的語境不同,父類要表達的含義是 is-a, 而代理要表達的含義更接近於接口, 是 has-a,而且使用代理的話應了一句話"少用繼承,多用組合",要表達的意思其實也就是降低耦合度了
    • 相比起接口,他們實現的功能又不太一樣,語境都是has-a,不過接口是has-a-function,而代理對象時是has-a-object,這個object是has-a-function的object,此外,接口是為了說明這個類擁有什么功能,卻沒有具體實現,實現了多態,而代理對象不但擁有這個功能,還擁有這個功能的具體實現
    • 對於組合來說,他比組合更具靈活性,比如我們將代理對象設為private,那么我可以選擇只提供一部分的代理功能,例如Printer的某一個或兩個方法,又或者在提供Printer的功能的時候加入一些其他的操作,這些都是可以的

 

下面先來看PHP如何實現代理

 1 <html>
 2      <body>
 3         <?php
 4             class Printer {    //代理對象,一台打印機
 5                 public function printSth() {
 6                     echo 'I can print <br>';
 7                 }
 8                 
 9                 // some more function below
10                 // ...
11             }
12              
13             class TextShop {    //這是一個文印處理店,只文印,賣紙,不照相
14                 private $printer;
15                 
16                 public function __construct(Printer $printer) {
17                     $this->printer = $printer;
18                 }
19                 
20                 public function sellPaper() {    //賣紙
21                     echo 'give you some paper <br>';
22                 }
23                 
24                 public function __call($method, $args) {    //將代理對象有的功能交給代理對象處理
25                     if(method_exists($this->printer, $method)) {
26                         $this->printer->$method($args);
27                     }
28                 }
29             }
30              
31             class PhotoShop {    //這是一個照相店,只文印,拍照,不賣紙
32                 private $printer;
33                 
34                 public function __construct(Printer $printer) {
35                     $this->printer = $printer;
36                 }
37                 
38                 public function takePhotos() {    //照相
39                     echo 'take photos for you <br>';
40                 }
41                 
42                 public function __call($method, $args) {    //將代理對象有的功能交給代理對象處理
43                     if(method_exists($this->printer, $method)) {
44                         $this->printer->$method($args);
45                     }
46                 }
47             }
48             
49             $printer = new Printer();
50             $textShop = new TextShop($printer);
51             $photoShop = new PhotoShop($printer);
52             
53             $textShop->printSth();
54             $photoShop->printSth();
55         ?>
56      </body>
57  </html>

文印處理店和照相店都具有文印的功能,所以我們可以將文印的功能代理給一台打印機,這里打印機只有一個功能,假如打印機還有n個功能,我們使用__call()方法就能夠省去很多重復的代碼了

假如是使用繼承,這樣語境上就不合理,一個店顯然不應該繼承一台打印機

而使用接口,因為我們的功能實現都是一樣,也沒有必要去重新實現接口的功能

所以此處使用代理是最佳選擇

Java中的代理模式實現其實類似,只不過Java沒有__call()方法,還需要手動聲明printSth()方法,然后在方法體里去調用$printer的printSth()方法,此處就不再贅述了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM