1. 程式人生 > 實用技巧 >C#用巢狀的 for 迴圈實現列印圖形

C#用巢狀的 for 迴圈實現列印圖形

概述

代理模式的定義:代理模式給某一個物件提供一個代理物件,並由代理物件控制對原物件的引用。通俗的來講代理模式就是我們生活中常見的中介。

在直接訪問物件時帶來的問題,比如說:要訪問的物件在遠端的機器上。在面向物件系統中,有些物件由於某些原因(比如物件建立開銷很大,或者某些操作需要安全控制,或者需要程序外的訪問),直接訪問會給使用者或者系統結構帶來很多麻煩,我們可以在訪問此物件時加上一個對此物件的訪問層。

舉個例子來說明:假如說我現在想買一輛二手車,雖然我可以自己去找車源,做質量檢測等一系列的車輛過戶流程,但是這確實太浪費我得時間和精力了。我只是想買一輛車而已為什麼我還要額外做這麼多事呢?於是我就通過中介公司來買車,他們來給我找車源,幫我辦理車輛過戶流程,我只是負責選擇自己喜歡的車,然後付錢就可以了。

代理模式的結構與實現

代理模式的結構比較簡單,主要是通過定義一個繼承抽象主題的代理來包含真實主題,從而實現對真實主題的訪問,下面來分析其基本結構和實現方法。

代理模式的主要角色如下。

  1. 抽象主題(Subject)類:通過介面或抽象類宣告真實主題和代理物件實現的業務方法。

  2. 真實主題(Real Subject)類:實現了抽象主題中的具體業務,是代理物件所代表的真實物件,是最終要引用的物件。

  3. 代理(Proxy)類:提供了與真實主題相同的介面,其內部含有對真實主題的引用,它可以訪問、控制或擴充套件真實主題的功能。

其結構圖如圖 所示。

為什麼要用代理模式?

  • 中介隔離作用:在某些情況下,一個客戶類不想或者不能直接引用一個委託物件,而代理類物件可以在客戶類和委託物件之間起到中介的作用,其特徵是代理類和委託類實現相同的介面。

  • 開閉原則,增加功能:代理類除了是客戶類和委託類的中介之外,我們還可以通過給代理類增加額外的功能來擴充套件委託類的功能,這樣做我們只需要修改代理類而不需要再修改委託類,符合程式碼設計的開閉原則。代理類主要負責為委託類預處理訊息、過濾訊息、把訊息轉發給委託類,以及事後對返回結果的處理等。代理類本身並不真正實現服務,而是同過呼叫委託類的相關方法,來提供特定的服務。真正的業務功能還是由委託類來實現,但是可以在業務功能執行的前後加入一些公共的服務。例如我們想給專案加入快取、日誌這些功能,我們就可以使用代理類來完成,而沒必要開啟已經封裝好的委託類。

代理模式的定義與特點

代理模式的主要優點有:

  • 代理模式在客戶端與目標物件之間起到一箇中介作用和保護目標物件的作用;

  • 代理物件可以擴充套件目標物件的功能;

  • 代理模式能將客戶端與目標物件分離,在一定程度上降低了系統的耦合度,增加了程式的可擴充套件性

其主要缺點是:

  • 代理模式會造成系統設計中類的數量增加

  • 在客戶端和目標物件之間增加一個代理物件,會造成請求處理速度變慢;

  • 增加了系統的複雜度;

有哪幾種代理模式?

我們有多種不同的方式來實現代理。如果按照代理建立的時期來進行分類的話, 可以分為兩種:靜態代理、動態代理

靜態代理是由程式設計師建立或特定工具自動生成原始碼,在對其編譯。在程式設計師執行之前,代理類 .class 檔案就已經被建立了。動態代理是在程式執行時通過反射機制動態建立的。

1、靜態代理

一步:建立服務類介面

package main.java.proxy;

public interface BuyHouse {
    void buyHosue();
}

第二步:實現服務介面

import main.java.proxy.BuyHouse;

public class BuyHouseImpl implements BuyHouse {

    @Override
    public void buyHosue() {
        System.out.println("我要買房");
    }
}

第三步:建立代理類

package main.java.proxy.impl;

import main.java.proxy.BuyHouse;

public class BuyHouseProxy implements BuyHouse {

    private BuyHouse buyHouse;

    public BuyHouseProxy(final BuyHouse buyHouse) {
        this.buyHouse = buyHouse;
    }

    @Override
    public void buyHosue() {
        System.out.println("買房前準備");
        buyHouse.buyHosue();
        System.out.println("買房後裝修");

    }
}

第四步:編寫測試類

import main.java.proxy.impl.BuyHouseImpl;
import main.java.proxy.impl.BuyHouseProxy;

public class ProxyTest {
    public static void main(String[] args) {
        BuyHouse buyHouse = new BuyHouseImpl();
        buyHouse.buyHosue();
        BuyHouseProxy buyHouseProxy = new BuyHouseProxy(buyHouse);
        buyHouseProxy.buyHosue();
    }
}

靜態代理總結:

優點:可以做到在符合開閉原則的情況下對目標物件進行功能擴充套件。

缺點:我們得為每一個服務都得建立代理類,工作量太大,不易管理。同時介面一旦發生改變,代理類也得相應修改。

2、動態代理

在動態代理中我們不再需要再手動的建立代理類,我們只需要編寫一個動態處理器就可以了。真正的代理物件由JDK再執行時為我們動態的來建立。

關於動態代理的實現,以及原始碼的分析,可以參看我之前寫的文章:深入理解 Java 動態代理機制

代理模式的應用場景

前面分析了代理模式的結構與特點,現在來分析以下的應用場景。

  • 遠端代理,這種方式通常是為了隱藏目標物件存在於不同地址空間的事實,方便客戶端訪問。例如,使用者申請某些網盤空間時,會在使用者的檔案系統中建立一個虛擬的硬碟,使用者訪問虛擬硬碟時實際訪問的是網盤空間。

  • 虛擬代理,這種方式通常用於要建立的目標物件開銷很大時。例如,下載一幅很大的影象需要很長時間,因某種計算比較複雜而短時間無法完成,這時可以先用小比例的虛擬代理替換真實的物件,消除使用者對伺服器慢的感覺。

  • 安全代理,這種方式通常用於控制不同種類客戶對真實物件的訪問許可權。

  • 智慧指引,主要用於呼叫目標物件時,代理附加一些額外的處理功能。例如,增加計算真實物件的引用次數的功能,這樣當該物件沒有被引用時,就可以自動釋放它。

  • 延遲載入,指為了提高系統的效能,延遲對目標的載入。例如,Hibernate中就存在屬性的延遲載入和關聯表的延時載入。

代理模式和裝飾器模式的區別

讓別人幫助你做你並不關心的事情,叫代理模式

為讓自己的能力增強,使得增強後的自己能夠使用更多的方法,拓展在自己基礎之上的功能的,叫裝飾器模式。

對裝飾器模式來說,裝飾者(decorator)和被裝飾者(decoratee)都實現同一個介面。

對代理模式來說,代理類(proxy class)和真實處理的類(real class)都實現同一個介面。他們之間的邊界確實比較模糊,兩者都是對類的方法進行擴充套件,具體區別如下:

  1. 裝飾器模式強調的是增強自身,在被裝飾之後你能夠在被增強的類上使用增強後的功能。增強後你還是你,只不過能力更強了而已;代理模式強調要讓別人幫你去做一些本身與你業務沒有太多關係的職責(記錄日誌、設定快取)。代理模式是為了實現物件的控制,因為被代理的物件往往難以直接獲得或者是其內部不想暴露出來。

  2. 裝飾模式是以對客戶端透明的方式擴充套件物件的功能,是繼承方案的一個替代方案;代理模式則是給一個物件提供一個代理物件,並由代理物件來控制對原有物件的引用;

  3. 裝飾模式是為裝飾的物件增強功能;而代理模式對代理的物件施加控制,但不對物件本身的功能進行增強;