第三章 分析 PBP Java AWT
3.4 class 的設計模式
模式就是不斷重複出現的現象。設計模式就是找出 class 之間的互動不斷出現 的現象,並且表示出這個模式背後的設計理念。了解設計模式可以幫助我們了解系 統,提供了系統的脈絡,也可以藉此來描述系統的準則與策略。Java AWT 基本功 能為移植和修改的基礎。分析 PBP 中的 Java AWT 基本功能 class,畫出 class 的 interaction diagram 如圖 6。
根據[2] [3]裡的定義,分析出圖 6 Java AWT 基本功能 class 的 interaction diagram 有 Observer, Composite, Adapter, Strategy, Abstract Factory, Singleton 六種設計模式,
接下來將會一一說明。
圖 6 Java AWT 基本功能 class 的 interaction diagram
Observer,Composite,Adapter 模式
Observer 模式定義:在物件間去定義一個一對多的依存關係,使得當一個物件狀態改 變時,所有與它相依的物件也都會被通知,並且自動更新。
圖 7 Java AWT class 與 Observer,Composite,Adapter 模式的關係
Component 與 EventListener 存在著 Observer 模式的關係。與模式相關的 class 關係如圖 7。Component 為被觀察者(Subject),EventListener 為觀察者(Oberver)。被 觀察者發生狀態改變時,需要通知觀察者,觀察者再依照改變的狀態執行相對應的 動作。EventListener 會先向註冊 Component,註冊需要觀察的事件(Event),例如 MouseEvent、KeyEvent。當 Component 接到了 Event,就會根據 Event type 去通知 EventListener 並把 event 傳遞它,EventListener 接到屬於自己觀察的事件時,就會 負責執行動作。
Window 與 Component 存在著 Oberver 模式的關係。與模式相關的 class 關係如圖 7。當 Window 接到底層傳上來的 event,就會委託 LightweightDispatcher 去分配 event,
LightweightDispatcher 就會按照 Event 的座標,自行計算出 cursor 或 mouse 的鎖定 的 target Component,並將 Event 傳遞給它。如果是 key event 或 focus event 直接傳 給 programer 設定好的 focus Component。接著 Component 再根據 event type 傳遞給 eventlistener,eventlistener 再做相對應的動作。
Composite 模式定義:將物件組合成樹狀結構用來表示全部的階層關係。使用的目的
是讓使用者用相同觀點看待單一物件或是組合物件。
Component 與 Container 存在著 Composite 的模式關係如圖 7。站在系統的角度,
Container 在抽象概念上屬於 Component,系統將它視為一繪圖元件,有著繪圖元件 的所有行為,所以繼承自 Component。實際上 container 是一集合概念,而 Component 是集合中的每一個 element。它所有的繪圖行為都是為了同時實現多個 Component 繪圖行為,除此之外 container 還有負責管理的工作,例如根據畫面佈置,決定這些 Component 的位置,或是給定一個座標,找出此座標屬於哪一個 Component 範圍內。
系統會根據不同的情形會想將所有的 Component 進行分組,不同組的 Component 會被分派到執行不同的工作,或是相同的工作,但每一組裡 Component 會執行不一 樣的步驟。這時需要統一管理同一組裡的 Component。指定它們同時進行相同或不
同動作,或是想要在 Component 彼此之間進行的互動時,就可以使用 container 來 負責執行這些動作。
Adapter 模式定義: 轉換物件的介面成另一個使用者所期望的介面。Adapter 使那些
因為不相容的介面而不能一起工作的物件得以連結。
Window 與 LightweightDispatcher 存在著 Adapter 的模式關係。與模式相關的 class 關係如圖 7。因為所有的 Component 都具備有 dispatch event 的功能,但正常情況下 此功能都是將 event 分配給已註冊在 Component 上的 EventListener。Window 有別 於其他的 Component,Window 除了分配 event 給 EventListener 之外,也負責將 event 分配給其它 lightweight Component,而這工作就委託 LightweightDispatcher 去執行。
Strategy 的模式
Strategy 模式定義:定義一個演算法家族,把他們每一個都包裝起來,並使它們可
以互相交換。Strategy 讓演算法可以與使用它的使用者獨立。
Container 與 LayoutManager 存在著 Strategy 的關係。與模式相關的 class 關係如
圖 8。Container 其中重要的一個功能就是負責畫面的佈置,實作的內容就是排列 Component 的位置。根據想要觀看的畫面,有許多不同設計擺放的方式。一邊實作 視窗元件 Component 的功能面的同時還要去顧慮畫面的佈置,為了減少程式設計的 負擔,於是將畫面佈置特別獨立出來,與原本程式設計的邏輯區分出來。畫面佈置
圖 8 Java AWT class 與 Strategy 模式的關係
是不依賴任何視窗元件功能,只要根據不同需求就可以進行實現,所以視為是一種 策略。不同策略就只是演算法上的不同。Strategy 就表示相同的目標(context)要實現 的功能可以由不同的演算法(strategy)來實現。Container 中負責畫面佈置的功能以 LayoutManager 來表示,那實作 LayoutManager 的 class 就是實作許多不同安排位置 的演算法,例如像是 FlowLayout,水流式版面配置屬於一種簡易的版面配置方式,
實際動作就是依序在同一列放置元件,沒有任何特殊編排,如果元件超過邊界,就 置於下一列。
Abstract Factory, Singleton 的模式
圖 9 Java AWT 與 AbstractFactory、Singleton 模式的關係
Abstract Factory 模式定義: 提供一個創造相關或相依的物件家族而不需要指定他
們具體的物件。有些物件在初始時會根據不同情形做設定,在這樣的情況下,
Abstract Factory 確保在不需要考慮如何產生的細節之下,能產生正確的物件。
在不同平台下,需要不同組的 Image、GraphicsEnvironment、Graphics、EventQueue,
稱為 Product (abstract class 為 abstract product,一般 class 為 concrete product),初始 這些物件的控制是相關的。負責產生這些物件的稱為 Factory(abstract class 為 abstract factory,一般 class 為 concrete factory),Toolkit 就是 Factory。它們跟 Toolkit 就是 Abstract Factory 模式的關係。與模式相關的 class 關係如圖 9。在這樣關係中,Toolkit 就是提供了整個 Java AWT 系統或與平台相關的功能。
Factory 與各個 Product 的在 Java 中的重要性以下會說明:
Toolkit 是實作系統與平台相關的功能,用來產生 peer Component,但在 Java ME PBP 中大都是 lightweight Component,所以沒有此功能。除此之外,還提供三種服 務:桌面量度(desktop metrics)、獲得字型資訊、影像下載與準備。Toolkit 透過產生 GraphicsEnvironment 物件來取得底層環境相關細節,提供桌面量度、字型資訊的服 務。還有系統中共同會使用到的 Graphics 和 EventQueue 物件。以及執行影像下載 與準備的 Iamge 物件。
EventQueue 用來管理 event。Component 可以不用管理自己的 event,可將所有管 理 event 責任統一交由 EventQueue 負責。透過 EventQueue 的 method 可以來操作 event。Component 產生完 event 時,就會呼叫 EventQueue 中 postEvent(),將新產生 的 event 丟到此 EventQueue 中,EventQueue 會根據 event 被放入的時間與優先權決 定 event 的順序。EventDispatcherThread 則固定一段時間就會呼叫 EventQueue 中 getNextEvent()將 event 取出,並把 event 分配。
Graphics 用來執行各種幾何圖形畫圖動作的 class。當執行時需要顯示 Component 時,就會執行 Component 中 paint()裡的演算法。此部分的演算法是 programmer 是 根據想要的外觀去呼叫 Graphics 裡的各種幾何畫圖動作的 method 所組成的,例如 畫線、畫圓等。在 lightweight Component 中,外觀是可以自行設計,有別於 Java SE
的 heavyweight Component,其外觀與樣式由不同平台預先設定好的,所以使用 Component 時沒有設計的權利,比較方便但減少了設計的空間。Graphics 扮演著很 重要的角色,而 Graphics 裡所有畫圖動作的快慢在程式的執行速度上佔有決定性的 影響力。
Image 是個記憶體上的一個物件且可以被顯示。藉由呼叫 Component 或 Toolkit 的 getImage()可以來載入 Image,然後藉由 Graphics 的 drawImage 顯示到螢幕上。
Image 是個 abstract class,由平台設定的 class 來實作,例如 MWImage。
GraphicsEnvironment 代表處理圖像的環境,也就是特定機器處理圖像的整體能力,
包括字形、螢幕裝置….等等。目前透過這個 class 的可以取得環境的字型資訊,還 有確定裝置的類型。一開始在初始 window 物件就會啟動此 class 的物件。在 Microwindow 的實作上,主要的功能除了建立裝置(GraphicsDevice)物件外,也會在 建立一個 Java thread。負責在底層環境中執行等待與接受 event 的動作,然後將 event 包裝成 Java event 傳遞上來。
Singleton 模式定義: 會使用 singleton 的目的是,確保此 class 只有一個 instance,並
且以一個 global variable 的觀點來使用它。
Toolkit 有著 singleton 模式的關係,與模式相關的 class 關係如圖 9。在 AWT 中,
Toolkit 提供許多工具給所有的物件使用,所以會不斷被用到,但不想要一直重覆 initialize 其物件,造成 garbage collection 清除工作的負擔。所以產生一個物件後,
所有的 class 或 object 使用時輪流去得唯一物件。。