Pattern-Oriented Software Architecture v1巨詳細讀書筆記 5

本筆記是《Pattern-Oriented Software Architecture vol.1 A system of patterns》原書[page 295-300]的山寨翻譯:),包括了View Handler模式的[動態]和[實現]兩小節。

-------------------------------------------------

 [動態]

我們選擇了2個場景來示例View Handler模式的的行爲:視圖的創建和排列。兩個場景都假定每個視圖都顯示在他自己的窗口中。
[296]
場景1 顯示了View Hanlder如何創建一個新的View,此場景由四個階段組成:
    - 客戶端(可能是用戶或者另一個系統組件)調用View Handler打開一個特定的View。
    - View Handler實例並初始化這個View,爲實現更改的傳播機制,就像Publisher-Subscribe模式一樣,此View在其相應的supplier中註冊。
    - View Handler將此新的View添加到其內部的已經打開的View列表中。
    - View Handler調用View的函數顯示此View,此View打開一個新的窗口,從它的supplier中獲取數據,準備這些數據,並把他們呈現給用戶。
[圖]
場景2 圖示了View Handler是如何排列View的,我們簡單地假設只有兩個視圖是被打開的。這個場景被分爲三個階段:
    - 用戶執行排列所有已經打開窗口的命令,此請求被髮送給View Handler。
    - View Handler計算每個已打開View的大小和位置,並調用他們的resize和move方法。
[297]
    - 每個View都改變自己的位置和大小,設子相應的剪切區域,並刷新它顯示給用戶的圖像。我們這裏假定View都緩存了需要顯示的圖像,如果沒有緩存,則View在重新顯示它自己之前還需要從他們相關聯的supplier中重新獲取數據。
[圖]


[實現]
實現View Handler的結構由4步驟組成。我們假定supplier已經存在,並且包括了一套適於傳播更改的機制。
    1 識別所有的View。識別出需要提供的視圖類型,並確定用戶如何操控每個獨立的View。
    2 描述一個所有View的公共接口,此接口應該包括:打開,關閉,顯示,更新和操控view的功能,也可以提供初始化View的功能,用特定的supplier中的數據配置view。將此接口封裝進一個抽象類中,可以爲例如視圖更新這樣的功能提供缺省實現。
    在我們的文檔編輯器的例子中,定義了類AbstractView,在此類中的protected的方法包括了顯示和刪除窗口的功能,也包括顯示窗口內容的功能,在public方法中包括對View:初始化、打開、關閉、移動、縮放、拖動和更新操作。
[298]
    class Abstractview {
    protected:
        // Draw the view
        virtual void displayData() = 0;
        virtual void displayWindow(Rectang1e boundary) = 0;
        virtual void eraseWindow() = 0;
    public:
        // Constructor and Destructor
        AbstractView ( ) {} ;
        ~AbstractView() { } ;
        // Initialize the view
        void initialize() = 0;
        // View handling with default implementation
        virtual void open(Rectang1e boundary) { /* . . . */ } ;
        virtual void close() ( /* . . . * / };
        virtual void move(Point point) { /* ... */ } ;
        virtual void size(Rectang1e boundary) { /* ... */ } ;
        virtual void drag(Rectang1e boundary) { /* ... */ } ;
        virtual void update () { /* . . . */ } ;
    };
    3 實現每個View。對於每個在第一步驟中識別出的特定類型,都從Abstractview繼承一個獨立的View類,在特定View中實現如我們例子中的displayData()一樣的特定方法,並重寫(override)缺省實現不滿足需求的方法。
    如果View Handler實現了特定的協調和更新策略,則View必須把所有影響其他View的事件通知給View Handler知道。例如,調整一個View的大小有可能會將之前遮擋到的其他View的某部分顯示出來,如果是View Handler來協調這些View的更新,則調整的View應該把此調整事件通知給View Handler知道。Publisher-Subscribe模式能幫助實現這種更改通知機制。
    在解決方案一節我們的例子中,我們實現了3個View類:EditView,LayoutView和ThumbnailView,他們都不需要重寫從AbstractView中繼承方法的缺省實現。
    4 定義View Handler。可以像Factory Methods模式[GHJV95]一樣實現創建View的方法。Client能指定他們所需要的View,但是他們不能控制如何創建View,View Handler負責實例並初始化正確的View組件。
[299]
    View Handler在內部維護所有已經打開的View的引用,Iterator模式[GHJV95]對實現此功能有所幫助。View Handler也許還維護如屏幕上窗口當前位置和大小這樣的View附加信息,這些信息在View Handler提供的如窗口克隆這樣的管理功能中會用到。
    View Handler也許需要實現應用程序特定的View協調策略,例如,一個View呈現另一個View的信息,動作類似的日誌信息。當排列兩個相互依賴的View時,需要將他們挨着排放;或者當他們都被最小化的時候,打開一個View將把另一個也打開。
    更新策略是View協作的另一個例子,也許必須優先更新特定View,如:顯示告警的View也許需要在打開其他View之前更新,在這種情況下,supplier將改動通知給View handler而不是依賴於他的View,View Handler採取一定的更新策略將此請求轉發給受影響的View。協調View更新的View Handler通常在他們的公共接口中提供一個更新函數。
    爲了使協作策略能更換,可以採用strategy模式[GHJV95]來實現這些策略。Mediator模式[GHJV95]爲實現View協作提供幫助,如:在所有打開的View中廣播刷新請求。也可以用Singleton模式[GHJV95]確保View Handler只能被實例化一次。
    在我們的例子文檔編輯器中的View Handler提供了打開、關閉、排列、置前、克隆View的功能。在View Handler內部維護了所有已經打開的View的引用,還包括他們的位置和大小、是否已經最小化等信息。
    class ViewHandler {
        // Data structures
        struct ViewInfo {
            Abstractview* view;
            Rectangle boundary;
            boo1 iconized;
        } ;
[300]
        Container<ViewInfo*> myviews;
        // The singleton instance
        static ViewHandler* theViewHandler;
        // Constructor and Destructor
        ViewHandler ( ) ;
        ~ViewHandler();
    public:
        // Singleton constructor
        static ViewHandler* makeViewHandler0 ;
        // Open and close views
        void open (Abstractview* view) ;
        void close(AbstractView* view);
        // Top, clone, and tile views
        void top (AbstractView* view) ;
        void clone(); // Clones the top-most view
        void tile ( ) ;
    } ;

以下代碼爲創建新View提供示例,defaultBoundary是Rectangle類的對象,定義了每個新窗口的缺省位置和大小,這段代碼實現了[動態]一節中的場景一。

    void ViewHandler::openView(AbstractView* view) {
        ViewInfo* viewInfo = new ViewInfo ( ) ;
        // Add the view to the list of open views
        viewInfo ->view = view;
        viewInfo->boundary = defaultBoundary;
        viewInfo->iconized = false;
        myviews.add (viewInfo) ;
        // Initialize the view and open it
        view->initialize () ;
        view->open(defaultBoundary);
    };
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章