剪貼簿中的觀察者 Observer 模式

2021-04-13 08:11:43 字數 1382 閱讀 5296

在windows提供的剪貼簿api中,針對監視這塊,提供的是註冊機制。主要函式是setclipboardviewer這個api函式。這個函式的宣告是這樣的(delphi):

functionsetclipboardviewer(hwndnewviewer: hwnd): hwnd;stdcall;

通過這個函式,將乙個視窗控制代碼,註冊到系統剪貼簿中。可以稱註冊後的窗體為乙個clipboard viewer,眾多的viewer形成乙個clipboard viewer chain。這個chain是乙個典型的鍊錶,前乙個記住下乙個的指標。

註冊為viewer的handle所在的窗體,通過處理wm_changecbchain和wm_drawclipboard兩個訊息,來處理所有來自剪貼簿的變化。處理這些訊息的時候,記住向下乙個viewer傳遞訊息,**類似於

sendmessage(hwndnextviewer, message, wparam, lparam);

我重點並不是要說明**如何編寫,只是簡單地介紹了這個「監控」的實現方式。我們很容易聯想到,這和設計模式中提到的observer模式是非常類似的。最大的不同點在於,剪貼簿直接使用了訊息系統作為解耦的方式。

正因為有這個相似的地方,我才願意仔細分析一下這種實現方式的優點和缺點。

先來說說優點:

目標和觀察者之間完全解耦,不需要定義特定介面。

觀察者可以在任意window上附加實現。這在很多窗體應用的程式來說非常方便。

可以很方便地實現跨程序、執行緒的觀察者。這得益於標準的訊息機制。

跨語言實現沒有什麼問題。

使用postmessage和sendmessage可以實現兩種完全不同的更新方式。subject可以選擇等待和不等待observer更新完成。

看了這些有點,最重要也是最核心的,就是解耦。再來分析一下缺點:

程式設計的過程,必須做到約定程式設計。約定程式設計和契約程式設計最大的差異在於沒有編譯機制。

在觀察者中可以方便地改變後續觀察者的行為,也可能完全破壞其他的正常功能。據說netants曾經在這方面就有過bug,導致其他程式無法貼上資料。

一般我們的應用場景中,除了m-v(模型-檢視)的模式,還有m-m(模型-模型)的方式,針對第二種方式,這種實現方式不是很適合。

沒有訊息系統的程式中,不適合使用。比如控制台程式。

對響應時間要求很高的系統,不適合。因為訊息的響應時間不可控制。

分析完上面的這些有點和缺點,我其實更傾向於從這類設計中吸取message這個設計元素。巧妙地使用message,可以有意想不到的效果。

總結一下,設計模式的基本原則之一就是解耦,而message的特性之一就是解耦。這也就是為什麼我們會發現剪貼簿的監視方式和我們學習的observer模式很想像的根本。所以說他是模式一點也不為過。只不過少了點oo的味道。

剪貼簿中的觀察者 Observer 模式

在windows提供的剪貼簿api中,針對監視這塊,提供的是註冊機制。主要函式是setclipboardviewer這個api函式。這個函式的宣告是這樣的 delphi functionsetclipboardviewer hwndnewviewer hwnd hwnd stdcall 通過這個函式...

VC的剪貼簿操作

1 文字內容的操作 2 wmf資料的操作 3 點陣圖的操作 4 設定使用自定義格式 5 感知剪貼簿內容的改變 6 自動將資料貼上到另一應用程式視窗 一 文字內容的操作 下面的 示範了如何將文字內容複製到剪貼簿 unicode編碼的先轉化為ascii cstring source 文字內容儲存在sou...

剪貼簿延遲提交的實現

剪帖板延遲提交即程式要與其它程式交換資料使用剪帖板時,在成為剪帖板所有者時並不將資料拷貝到剪帖板中,而是將剪帖板清空,在有程式需要剪帖板資料時,window會給當前的剪帖板所有者傳送訊息,要求提供剪帖板資料。這種情況一般用在多種剪帖板格式提供時。1。首先清空剪帖板 if openclipboard ...