《UML面向对象设计基础》—第1章1.5节消息
本節書摘來自異步社區《UML面向對象設計基礎》一書中的第1章1.5節消息,作者【美】Meliir Page-Jones,更多章節內容可以訪問云棲社區“異步社區”公眾號查看。
1.5 消息
UML面向對象設計基礎
對象通過消息請求另一個對象執行活動。許多消息還具有將信息從一個對象傳送給另一個對象的作用。大多數老前輩都將消息列為重要的面向對象特性。
消息(message)是發送對象obj1向目標對象obj2發送請求的載體,申請對象obj2的一個方法。
本節對消息特性進行了剖析,描述了消息參數的特點,發送消息對象的角色,接收消息對象的角色及消息的三種類型。
1.5.1 消息結構
消息由幾個含義組成,每個含義在面向對象設計中都十分重要。實際上,本書從頭到尾會多次用到消息的特性。
對象obj1為給對象obj2發送一個顯式消息,對象obj1必須知道三件事情:
① obj2的句柄。顯然,你發送一個消息時,應該知道給誰發送。obj1通常將obj2的句柄保存在它的一個變量中。
② obj1希望執行的obj2操作名稱。
③ obj2執行其操作時所要求的所有附加信息(參數)。
發送消息的對象(obj1)稱為發送者,接收消息的對象(obj2)稱為目標對象,也可以分別稱為客戶機(Client)和服務器(Server)。
機器人軟件提供了幾個消息的例子,其中一個為:
hom1.turnRight;
其中,hom1表示該消息(含有句柄)的目標對象。回想一下,賦值語句。
var hom1 :=Hominoid.New給hom1賦的句柄)。turnRight是目標對象執行操作的名稱。這個消息不需要任何參數:turnRight總是旋轉90°。
發送消息和調用傳統的函數或過程有些類似。如用“準O.O.”語言,可以寫出下面的語句:
call turnRight(hom1);請注意這種倒置:使用傳統的軟件技術,我們先申請一個過程單元,然后向其提供操作的對象;在面向對象中,我們先申請一個對象,然后執行其中一個過程單元。
到此為止,這種區別似乎只停留在語法上,至多是觀念上的。然而,當我在1.8節討論多態性、重載及動態關聯時,將體會到“先對象后過程”所引起的面向對象結構和傳統結構之間的重要差別。因為不同的對象類可以使用相同的操作名稱執行不同特定類的行為,或執行含義不同的類似行為。
1.5.2 消息參數
與傳統的子程序一樣,大多數消息都可以傳入或傳出參數。例如,如果名為 advance的操作返回一個標志,保存行進的輸出,于是有下面的形式:
因此,給予目標對象的消息結構由激活目標操作的原形(signature)所定義。這個原形包括三個部分:操作名稱,輸入參數列表(前綴為 in),輸出參數列表,也稱返回參數(前綴為out)。每個參數列表都可以為空,在兩個列表中可能出現相同的參數或只在前綴為inout的列表中出現一次,但在純面向對象中很少出現這種情形。為簡短起見,通常省略關鍵字in,將其作為缺省前綴。
消息的參數反映了面向對象軟件和傳統軟件之間的另一個基本區別。在純面向對象環境中(如Smalltalk),消息參數不是數據,而是對象句柄,因此,消息參數也當作對象。
例如,圖1.10a以非正式的圖形表示法說明了機器人程序中的一個消息:
hom1.advance(noOfSquares,out advanceOK)。
如果在執行消息時暫停hominoid程序的執行,取出消息參數的值,我們將發現意想不到的結果。如:
noOfSquare被置為123432
advanceOK 被置為664730
為什么會得到這些奇怪的數字?因為123432可能為對象(Integer類)的句柄,通常為整數2,664730可能為對象(Boolean類)的句柄,通常為邏輯值true,在面向對象環境中最好不用這些精確的數字,我使用這些數字只是用于說明。
如果你更喜歡圖1.10b用UML表示方法來表示這個消息,第3章至第7章將會更深入地討論這方面內容。
另外,再舉一個例子,如果我們正執行一個面向對象的個人系統并做相同的事情,可能發現參數empOfMonth被置為441523。441523可能是對象(Employee類)的句柄表示Jim Spriggs先生。
1.5.3 消息中的對象角色
本節討論面向對象系統中對象的四個角色。一個對象可以是:
消息的發送者。
消息的目標。
表示另一個對象中的變量(見1.4節)。
表示消息中傳入和傳出的參數(見1.5.2節)。
一個給定的對象在生存期可以扮演一個或多個角色。在圖1.11中,我們可以看到所有這些角色。
從這個圖1.11中,我們來看一下對象obj的一個操作op。這個操作發送消息給obj的三個變量指向的每一個對象。第一個消息只有一個輸入參數;第二個消息只有一個輸出參數;第三個消息既有輸入參數也有輸出參數。每個參數本身指向一個對象。這個結構非常典型地說明了對象操作如何與對象變量進行交互。
一些作者建議每個對象要么是“發送者”要么是“目標”。但實際不然,如圖1.12所示。
對于message1,obj1是發送者,obj2是目標。對于message2,obj2是發送者,obj3是目標。因此我們看到,不同的時刻,同一個對象既可以是發送者又可以是目標。術語“發送者”和“目標”是相對給定消息而言的。它們不是對象本身固有的特性。
在純面向對象環境中只有對象,每個對象扮演一個或前面提到的四個角色中的幾個角色。在純面向對象中不需要數據,因為對象可以完成數據完成的所有軟件功能。在Smalltalk(非常純的面向對象語言)中,確實沒有任何數據!運行時只有指向其他對象的對象(通過變量),通過傳遞對象的句柄進行對象之間的通信。
但在C++(一種既面向數據或函數又面向對象的混合語言)中,參數可以表示任何信息。如果你的C++程序與Smalltalk一樣純,那么所有的參數都表示對象。但如果你將數據和對象混合在C++程序中,那么有一些參數就是簡單的數據(或數據的指針)。對于Java語言也是如此,盡管Java語言遠遠不如C++那樣隨意。
1.5.4 消息的類型
對象可以接收三種類型的消息:報告消息,詢問消息及祈使消息。本節對每一種消息進行舉例說明。再一次借用機器人程序。在本書的最后第12章,討論通信對象不同的設計方法時,再回到這些消息類型。
報告消息(informative message)是指向對象提供自我更新信息的消息(也稱更新、向前或推出消息)。這是一種“面向過去”的消息,通常通知對象已經發生的事情。
報告消息的一個例子是employee.got(MarriageDate:Date)。這個消息告訴一個雇員對象某個雇員已經在某個日期結婚。通常,報告消息告訴一個對象由該對象表示的在現實世界中已經發生的事情。
詢問消息(interrogative message)是請求一個對象顯示自身一些信息的消息(也稱為讀、向后或回拉消息)。這是一種“面向現在”的消息,向對象詢問當前信息。
詢問消息的一個例子是hom1.location,向機器人詢問當前所在的方格位置。這類消息實際上不改變任何事情,通常是向目標對象詢問其表示的信息。
祈使消息(imperative message)請求對象對本身、另一個對象或系統環境執行某些操作(也稱強制或動作消息)。這是一種“面向未來”的消息,請求對象執行將來的某些操作。
祈使消息的一個例子是hom1.advance,使機器人向前移動。這種消息通常使目標對象執行一些重要的算法。
類似地,假設向機器人發送下面的祈使消息:
hom1.goToLocation(square:Square,out feasible:Boolean)
該消息請求機器人只要可行,就走到特定的方格(機器人執行的計算量非常大)。
在實時的面向對象系統中,對象需要控制一些硬件,通常包含許多祈使消息。這些系統清楚地說明將要執行的祈使消息。下面是取自機器人世界的一個例子:
robotLeftHand.goToLocation(x,y,z:Length,theta1,theta2,theta3:Angle)
這個消息將使機器人的左手抬到某個位置并在空間定位。該算法可能要求機器人的手、機器人的胳臂或機器人本身移動。六個參數表示了手的六個自由度,以三維空間表示。
下面讓我們從消息轉到面向對象公認的基本屬性即對象類。
本文僅用于學習和交流目的,不代表異步社區觀點。非商業轉載請注明作譯者、出處,并保留本文的原始鏈接。
總結
以上是生活随笔為你收集整理的《UML面向对象设计基础》—第1章1.5节消息的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学习angularjs的内置API函数
- 下一篇: 《Spark大数据分析:核心概念、技术及