很多書上會寫著,對象是具有數據以及對這些數據提供的操作的集合。這是一個極其錯誤的認識。這里的對象可以簡單理解為類似于現實生活中的對象,生活中是以對象為個體,并且不同對象間通過發送消息作為交流溝通方式。例如,社會的交換活動,任何人都是通過發送消息到另一個對象去請求其所提供的某種服務。整個面向對象系統就是以對象間的互相交互,協作形成的一個運行系統。 至于類,只是 同種性質的對象的抽象體,是一個抽象概念,它只是用來讓編譯器認識的。
每一個對象都提供某些服務,當然都是以方法的形式存在。而且,這些服務可能同時需要一些數據信息,這兩種即構成了對象對外提供服務的基礎。也是最常見的。那種理解為先有數據信息,再由服務是不對的,否則,將難于進行對象抽象以及設計。而且,這些方法不是專為數據服務或者說外界并不是為了訪問數據,而時這些數據根據服務的需要決定需要什么數據信息以及如何暴露數據信息。與此相反的訪問方式,抽象數據結構是個典型,這種方式以數據位中心,并不是面向對象的核心所在。 面向對象的核心是整個世界的寫作過程,是以服務為基石,它并不是以數據位中心,而是以服務為中心,各對象通過接口暴露自己的服務,為外界提供服務。這也是面向接口編程的主旨。所以面向對象應該是先有對象行為,而這些數據時反過來為這些行為提供數據基礎信息,為之提供數據服務的。這與傳統的ADT,數據+對數據的操作方法時截然不同的,盡管其結構及其相似,它是方法依賴于數據。
基于這些原因,一個無數據的對象出現時很正常的,而且是占據很大部分。這些對象稱之為無狀態對象。即兩個同類對象,其行為時完全一樣的,因為已經少了特定數據信息的依賴關系。現實生活中也確實存在這類只提供服務的對象,該對象提供的服務本身互相依賴,或同類,或是以某種一致的方式向外提供服務。而在面向對象的系統中,這種無狀態服務對象是基于業務需求而定的。同樣的對象,在一種業務系統中,它是有狀態對象,需要某些依賴信息,而在另一個系統中,可能就以無狀態對象出現,外界并不關注其數據,而只是想獲取其服務,這時這些數據信息并不存在意義,盡管它可以被保留住,對象里的服務于數據,存在服務依賴于數據,以及不依賴2種關系。然后,大部分是有依賴關系的,對于無狀態對象,有2種處理方式,其一,既然無狀態,則可分布至各自不同的Util類中,如
class A {
sourt(..);
run(..);
study(..);
}
這里A的任何對象都是無狀態的對象,則應放入不同Util類中并以static修飾它。這種無狀態類是不應該被設計的,因為他充滿了大雜燴的壞味道。職責不明確,更不用提SRP了。并且給這種類取名也是一個大問題。再看,
class OrderService {
add(...);
remove(...);
update(...);
}
這個OrderService的一個實例,同樣時無狀態對象,然而這是一個合理的設計。因為其很好的吻合了對象的語義所在。提供了一組一致,互相合作,同類服務的服務方式。
有時會有很多對象,其提供服務時相同的,但是其具體實現的內部細節不同,如:
基于class RemoteOrderService, class LocalOrderService所生成的對象,而且是很常見的,且其依賴的數據信息時不同的,這在生活中很存在的合理性。如
RunnerA {
run(...){
使用拖鞋跑
}
}
RunnerB {
run(...){
使用自行車跑
}
}
然而,我們無論創建RunnerA還是RunnerB的對象,我們都不關心其實現細節,也就是我們根本不關心內部數據的依賴細節,我們只關心其為我們提供的服務,它能使我從一個地方到達另一個地方。因而,其數據對我們而言是透明的。我根本不想知道,你是使用什么數據,怎么run的。因而這種基于服務提供的方式,使得我們使用了一個只包含所提供服務的類型Runner。并且在我們看來,它隱藏了提供的服務的實現細節,這就是接口。
interface Runner{
run(..);
}
而多態的性質,這時發揮了很好的作用。形成了一個種特殊的依賴關系,此時,client與Runner的依賴關系遠遠強于Runner與其實現類的依賴關系。這也就是面向對象幾大原則之一的DIP了。
因此,面向對象系統本質是以接口為核心的系統,每個接口就代替一個ServiceProvider, 然后,發送消息請求構成了一個協作系統網。
而另一種極端,就是對象無行為。當然,其是有狀態對象。這些對象都是不同的,盡管他們同屬一類。這種對象的出現,使得面向對象的語義受到了很大的沖擊。因為這種脫離了對象是以服務為核心的語義。一個對象沒了方法,那還談什么服務。然后,現實生活中的確是有些東西是無服務的,例如book, 而這種被稱為實體對象。這里并不是說該實體真的無服務,而是其所提供的服務其實是無用的,或無意義的。因此,寧愿將其行為全部去除以保持其整潔,又不至于冗余。因為這同樣取決于業務系統的需求。這一種情形被稱為貧血模型,即不具行為之對象。不管貧血與否,其設計起源于業務系統的需求。設計是多種多樣的的,面向對象本身要求從問題領域中提取對象是件難事,同時對象的職責分配更是一件難事。所以,出現了許多關于這方面的方法論,如CRC, 信息專家等職責分配方法以及大量面向對象設計原則,設計模式等等。因而,面向對象設計本身是一門高深的學問。并且取決于個人的經驗以及知識面,處理業務,分析,解決各種問題的思想,特別是基于某特定領域的業務經驗。
我們發現了再生活中的不基于服務的,不基于消息發送請求服務的對象,我們僅僅能說這些對象不直接參與對象協作網。因為沒人能透過該網享受或請求到某種服務。但是,它是作為一種間接寫作者出現,它作為其他對象間的請求服務的一種輔助,就好比交換系統中的物品,它是在服務對象間的請求鏈中流通,而流通過程中,沒有一個人會把請求發向該物品,他們可以持有它或流通它。當然,有可能在流通中,稍微檢查物品是否合法等。而這時該物品也僅僅提供了合法檢查服務而已。跟基于對象服務的協作網是大小巫了。呵呵。
根據面向對象設計原則以及經驗的權衡作出合理的設計時必需的。在這些不同的對象類型中,最容易被發現并提取的就是,貧血模型的對象。因為他直接反應世界,不是只有程序員能想到,而是生活中的所有人都懂。這就是面向對象的好處。在業務領域中,業務專家起到了相當重要的作用。這就是面向對象的好處。在業務領域中,業務專家起到了相當重要的作用。如,圖書管理系統,大家都會想到實體類,如book, student, library等等。這些就是不提供服務的對象。而且這些信息基本都會被持久化進DB或其他地方,散發著某些DB的味道,因而這些對象一旦被冠以DB味道后,大多數人的初衷發生了微妙的變化,他們把設計的焦點轉向了DB,而遠遠脫離了他原本想做的基于面向對象的設計,久而久之,很多人習慣了基于DB的設計,一個系統一上來就開始建立表。把所以業務邏輯寄托在DB身上。所以,DB責任之大可想而知。因為面向對象設計與之相比是何等之難。這時候,所有的業務邏輯都依賴于DB,整個業務系統設計嚴重側向DB,一些以表為核心。從一個表能看出所有業務,因為人們太習慣于關注信息了,而且DB是基于二維表的,從小學就學過,極其容易,管理層的家伙們很容易明白,這時管理層也參與了項目討論,很好。對著那些表,指著點著。這就是技術。
posted on 2009-10-29 08:49
zhqh 閱讀(368)
評論(1) 編輯 收藏 所屬分類:
面向對象