由于最早學(xué)的編程語(yǔ)言都是面向過(guò)程的沾谜,導(dǎo)致自己先入為主,對(duì)面向過(guò)程的印象特別深刻胀莹。而面向?qū)ο蠡埽m然一直都有學(xué)習(xí)和用到,也知道怎么新建對(duì)象描焰,函數(shù)媳否,怎么去使用。然而栈顷,始終覺(jué)得理解的差了那么一點(diǎn)逆日。
市面上的各類(lèi)教程,大多是教你如何在某個(gè)語(yǔ)言中萄凤,定義一個(gè)類(lèi),以及對(duì)應(yīng)的方法搪哪,然后再為這個(gè)類(lèi)新建一個(gè)對(duì)象靡努。之后再教你如何定義子類(lèi)繼承父類(lèi),等等晓折。
所舉的例子惑朦,大多也就是類(lèi)似這種:
定義動(dòng)物類(lèi)型,動(dòng)物會(huì)吃漓概,會(huì)睡漾月,吃和睡是方法,而示例中給出的方法實(shí)現(xiàn)胃珍,一般也就是簡(jiǎn)單的 print("吃"); print("睡")梁肿;然后定義子類(lèi)如鳥(niǎo)蜓陌,鳥(niǎo)又有新的方法比如會(huì)飛,會(huì)下蛋吩蔑;
這些簡(jiǎn)單的例子雖然清楚的描述了如何使用具體的語(yǔ)言去實(shí)現(xiàn)一個(gè)類(lèi)钮热,但是你卻很難把他們和實(shí)際工作中所要解決的問(wèn)題聯(lián)系起來(lái)。
比如:為什么要定義動(dòng)物類(lèi)型烛芬,為什么定義了吃和睡這兩種方法隧期,而不是定義生和死?
為什么要從動(dòng)物類(lèi)派生出鳥(niǎo)這個(gè)子類(lèi)赘娄,它又有什么用處仆潮?給出會(huì)飛和會(huì)下蛋的方法是否合理,是不是還有鳥(niǎo)不會(huì)飛或者不會(huì)下蛋的遣臼?
看這類(lèi)教程鸵闪,無(wú)法得到答案,并且理解更加浮于表面暑诸。導(dǎo)致看的越多蚌讼,對(duì)于面向?qū)ο蟮囊饬x以及背后隱藏的思想,越為迷糊个榕。
于是靜心坐下來(lái)看這么一本經(jīng)典的《Java編程思想》篡石,從深入了解對(duì)象開(kāi)始。
抽象過(guò)程
所有的編程語(yǔ)言都提供抽象機(jī)制西采。匯編語(yǔ)言是對(duì)底層機(jī)器語(yǔ)言的輕微抽象凰萨。許多所謂命令式語(yǔ)言(FORTRAN、BASIC械馆、C)是對(duì)匯編語(yǔ)言的抽象胖眷。
它們所做的主要抽象,要求在解決問(wèn)題時(shí)霹崎,基于計(jì)算機(jī)的結(jié)構(gòu)珊搀,而不是基于所要解決的問(wèn)題的結(jié)構(gòu)來(lái)考慮。
程序員需要在 機(jī)器模型 和 實(shí)際待解問(wèn)題的模型 之間 建立關(guān)聯(lián)尾菇。
另一種方式境析,是只對(duì)待解問(wèn)題建模。如LISP, APL, PROLOG等派诬。但是它們都有特定的應(yīng)用領(lǐng)域劳淆。
面向?qū)ο蠓绞绞牵虺绦騿T提供了表示問(wèn)題空間中的元素的工具默赂。問(wèn)題空間中的元素及其在解空間中的表示沛鸵,稱為“對(duì)象”。(還需要一些無(wú)法類(lèi)比為問(wèn)題空間元素的對(duì)象缆八。)
這種思想的實(shí)質(zhì)是:可以通過(guò)添加新類(lèi)型的對(duì)象曲掰,使自身適用于某個(gè)特定問(wèn)題疾捍。因此,當(dāng)在閱讀描述解決方案的代碼的同時(shí)蜈缤,也是在閱讀問(wèn)題的表述拾氓。
OOP允許根據(jù)問(wèn)題來(lái)描述問(wèn)題,而不是根據(jù)運(yùn)行解決方案的計(jì)算機(jī)來(lái)描述問(wèn)題底哥。
每個(gè)對(duì)象看起來(lái)都有點(diǎn)像一臺(tái)微型計(jì)算機(jī)——它具有狀態(tài)咙鞍,還有操作。和現(xiàn)實(shí)世界中的對(duì)象作類(lèi)比趾徽,可以說(shuō)他們都具有特性和行為续滋。
第一個(gè)成功的面向?qū)ο笳Z(yǔ)言,同時(shí)也是Java所基于的語(yǔ)言之一的Smalltalk的五個(gè)基本特性:
- 萬(wàn)物皆為對(duì)象
- 程序是對(duì)象的集合孵奶,它們通過(guò)發(fā)送消息來(lái)告知彼此所要做的
- 每個(gè)對(duì)象都有自己的由其他對(duì)象所構(gòu)成的存儲(chǔ)
- 每個(gè)對(duì)象都擁有類(lèi)型
- 某一特定類(lèi)型的所有對(duì)象都可以接收同樣的信息
一個(gè)更加簡(jiǎn)潔的描述:對(duì)象具有狀態(tài)疲酌、行為和標(biāo)識(shí)。
每個(gè)對(duì)象都擁有內(nèi)部數(shù)據(jù)——給出了該對(duì)象的狀態(tài)
方法——它們產(chǎn)生行為
可以唯一地與其他對(duì)象區(qū)分開(kāi)來(lái)——每一個(gè)對(duì)象在內(nèi)存中都有一個(gè)唯一的地址
每個(gè)對(duì)象都有一個(gè)接口
所有的對(duì)象都是唯一的了袁,但同時(shí)也是具有相同的特性和行為的對(duì)象所歸屬的類(lèi)的一部分朗恳。
因?yàn)轭?lèi)描述了具有相同特性(數(shù)據(jù)元素)和行為(功能)的對(duì)象集合,所以一個(gè)類(lèi)實(shí)際上就是一個(gè)數(shù)據(jù)類(lèi)型载绿。
二者的差異在于粥诫,程序員通過(guò)定義類(lèi)來(lái)適應(yīng)問(wèn)題,而不再被迫只能使用現(xiàn)有的用來(lái)表示機(jī)器中的存儲(chǔ)單元的數(shù)據(jù)類(lèi)型崭庸。
面向?qū)ο蠓椒ú⒉皇莾H局限于構(gòu)建仿真程序怀浆。任何程序都是你所設(shè)計(jì)的系統(tǒng)的一種仿真。
面向?qū)ο蟪绦蛟O(shè)計(jì)的挑戰(zhàn)之一怕享,就是在問(wèn)題空間的元素和解空間的對(duì)象之間創(chuàng)建一對(duì)一的映射执赡。
怎樣獲得有用的對(duì)象?
必須有某種方式產(chǎn)生對(duì)對(duì)象的請(qǐng)求函筋,使對(duì)象完成各種任務(wù)沙合。每個(gè)對(duì)象都只能滿足某些請(qǐng)求,這些請(qǐng)求由對(duì)象的接口(interface)所定義驻呐,決定接口的便是類(lèi)型灌诅。
類(lèi)型名稱 | Light |
---|---|
接口 | on() off() brighten() dim() |
Light lt = new Light();
lt.on();
接口確定了對(duì)某一特定對(duì)象所能發(fā)出的請(qǐng)求。在程序中必須有滿足這些請(qǐng)求的代碼含末。這些代碼與隱藏的數(shù)據(jù)一起構(gòu)成了實(shí)現(xiàn)。
每個(gè)對(duì)象都提供服務(wù)
當(dāng)正在試圖開(kāi)發(fā)或理解一個(gè)程序設(shè)計(jì)時(shí)即舌,最好的方法之一就是佣盒,將對(duì)象想象為“服務(wù)提供者”。
你的目標(biāo)就是顽聂,去創(chuàng)建(或者最好是在現(xiàn)有代碼庫(kù)中尋找)能夠提供理想的服務(wù)來(lái)解決問(wèn)題的一系列對(duì)象肥惭。
問(wèn)一下自己:“如果我可以將問(wèn)題從表象中抽取出來(lái)盯仪,那么什么樣的對(duì)象可以馬上解決我的問(wèn)題呢?”
分析之后蜜葱,也許某些對(duì)象已經(jīng)存在了全景,但是對(duì)于不存在的對(duì)象,看起來(lái)像什么樣子牵囤?能夠提供哪些服務(wù)爸黄?需要哪些對(duì)象才能履行他們的義務(wù)?
持續(xù)這樣做之后揭鳞,就會(huì)發(fā)現(xiàn):
- 我肯定某個(gè)對(duì)象已經(jīng)存在了炕贵。
- 某個(gè)對(duì)象看起來(lái)很簡(jiǎn)單,可以坐下來(lái)寫(xiě)代碼了野崇。
這樣称开,就將問(wèn)題分解為了對(duì)象集合。
將對(duì)象看作是服務(wù)提供者的另一個(gè)好處:有助于提高對(duì)象的內(nèi)聚性乓梨。
將對(duì)象作為服務(wù)提供者看待鳖轰,是一件偉大的簡(jiǎn)化工具:在設(shè)計(jì)過(guò)程中有用,當(dāng)其他人試圖理解你的代碼或重用某個(gè)對(duì)象時(shí)扶镀,如果看出了這個(gè)對(duì)象所能提供的服務(wù)的價(jià)值蕴侣,這會(huì)使調(diào)整對(duì)象以適應(yīng)其設(shè)計(jì)的過(guò)程變得簡(jiǎn)單。
被隱藏的具體實(shí)現(xiàn)
將程序開(kāi)發(fā)人員按照角色分為類(lèi)創(chuàng)建者(那些創(chuàng)建新數(shù)據(jù)類(lèi)型的程序員)和客戶端程序員(那些在其應(yīng)用中使用數(shù)據(jù)類(lèi)型的類(lèi)消費(fèi)者)是很有意義的狈惫。
客戶端程序員的目標(biāo)睛蛛,是收集各種用來(lái)實(shí)現(xiàn)快速應(yīng)用開(kāi)發(fā)的類(lèi)。
類(lèi)創(chuàng)建者的目標(biāo)是構(gòu)建類(lèi)胧谈,這種類(lèi)只向客戶端程序員暴露必備的部分忆肾,而隱藏其他部分。
Java用三個(gè)關(guān)鍵字在類(lèi)的內(nèi)部設(shè)定邊界:public菱肖、private客冈、protected。
public:緊隨其后的元素對(duì)任何人都是可用的稳强。
private:除類(lèi)型創(chuàng)建者和類(lèi)型的內(nèi)部方法之外的任何人都不能訪問(wèn)的元素场仲。
protected:與private作用相當(dāng),區(qū)別是退疫,繼承的類(lèi)可以訪問(wèn)protected成員渠缕,但是不能訪問(wèn)private成員。
Java還有一種默認(rèn)訪問(wèn)權(quán)限褒繁,當(dāng)沒(méi)有用到前面提到的訪問(wèn)指定詞時(shí)亦鳞,將發(fā)揮作用。這種權(quán)限是包訪問(wèn)權(quán)限。類(lèi)可以訪問(wèn)在同一個(gè)包中的其他類(lèi)的成員燕差,但是在包之外遭笋,這些成員如同指定了private一樣。
復(fù)用具體實(shí)現(xiàn)
最簡(jiǎn)單地復(fù)用某個(gè)類(lèi)的方式徒探,就是直接使用該類(lèi)的一個(gè)對(duì)象瓦呼,此外也可以將那個(gè)類(lèi)的一個(gè)對(duì)象置于某個(gè)新的類(lèi)中。我們稱其為“創(chuàng)建一個(gè)成員對(duì)象”测暗。
新的類(lèi)可以由任意數(shù)量央串、任意類(lèi)型的其他對(duì)象以任意可以實(shí)現(xiàn)新的類(lèi)中想要的功能的方式所組成。
組合:使用現(xiàn)有的類(lèi)合成新的類(lèi)偷溺。
聚合:組合是動(dòng)態(tài)發(fā)生的蹋辅。
組合帶來(lái)了極大的靈活性〈焯停可以在不干擾現(xiàn)有客戶端代碼的情況下侦另,修改這些成員。也可以在運(yùn)行時(shí)修改這些成員對(duì)象尉共,以實(shí)現(xiàn)動(dòng)態(tài)修改程序的行為褒傅。繼承并不具備這樣的靈活性,因?yàn)榫幾g器必須對(duì)通過(guò)繼承而創(chuàng)建的類(lèi)施加編譯時(shí)的限制袄友。
在建立新類(lèi)時(shí)撒会,應(yīng)該首先考慮組合荧库,因?yàn)樗雍?jiǎn)單靈活。一旦有了一些經(jīng)驗(yàn)之后,便能夠看出必須使用繼承的場(chǎng)合了媒吗。
繼承
對(duì)象這種觀念膛虫,使得你可以通過(guò)概念將數(shù)據(jù)和功能封裝到一起醒陆。這些概念用關(guān)鍵字class來(lái)表示宙搬,它們形成了編程語(yǔ)言中的基本單位。
可以創(chuàng)建一個(gè)基類(lèi)型來(lái)表示系統(tǒng)中某些對(duì)象的核心概念目尖,從基類(lèi)型中導(dǎo)出其他類(lèi)型馒吴,來(lái)表示此核心可以被實(shí)現(xiàn)的各種不同方式。
例如幾何形瑟曲,類(lèi)型層次結(jié)構(gòu)同時(shí)體現(xiàn)了幾何形狀之間的相似性和差異性饮戳。
以同樣的術(shù)語(yǔ),將解決方案轉(zhuǎn)換成問(wèn)題是大有裨益的洞拨,因?yàn)椴恍枰趩?wèn)題描述和解決方案描述之間建立許多中間模型扯罐。通過(guò)使用對(duì)象,類(lèi)型層次結(jié)構(gòu)成為了主要模型烦衣。因此篮赢,可以直接從真實(shí)世界中對(duì)系統(tǒng)的描述過(guò)渡到用代碼對(duì)系統(tǒng)進(jìn)行描述齿椅。
導(dǎo)出類(lèi)與基類(lèi)具有相同的類(lèi)型琉挖。前面的例子启泣,一個(gè)圓形也就是一個(gè)幾何形。通過(guò)繼承而產(chǎn)生的類(lèi)型等價(jià)性示辈,是理解面向?qū)ο蟪绦蛟O(shè)計(jì)方法內(nèi)涵的重要門(mén)檻寥茫。
有兩種方法可以使基類(lèi)與導(dǎo)出類(lèi)產(chǎn)生差異:
- 直接在導(dǎo)出類(lèi)中添加新方法。但是矾麻,應(yīng)該仔細(xì)考慮是否存在基類(lèi)也需要這些額外方法的可能性纱耻。
- 更重要的一種使導(dǎo)出類(lèi)和基類(lèi)之間產(chǎn)生差異的方法,是改變現(xiàn)有基類(lèi)的方法的行為险耀,這被稱之為覆蓋那個(gè)方法弄喘。
“是一個(gè)”與“像是一個(gè)“關(guān)系
繼承應(yīng)該只覆蓋基類(lèi)的方法嗎?
如果這樣做甩牺,就意味著導(dǎo)出類(lèi)和基類(lèi)是完全相同的類(lèi)型蘑志,因?yàn)樗麄兙哂?em>完全相同的接口。
我們經(jīng)常將這種情況下的基類(lèi)與導(dǎo)出類(lèi)之間的關(guān)系成為is-a(是一個(gè))關(guān)系贬派。
有時(shí)必須在導(dǎo)出類(lèi)型中添加新的接口元素急但,這樣也就擴(kuò)展了接口。此時(shí)基類(lèi)無(wú)法訪問(wèn)新添加的方法搞乏。
這種情況我們可以描述為is-like-a(像是一個(gè))關(guān)系波桩。
新類(lèi)型具有舊類(lèi)型的接口,但是它還包含其他方法请敦,所以不能說(shuō)它們完全相同镐躲。
伴隨多態(tài)的可互換對(duì)象
這部分沒(méi)太明白,后續(xù)再做筆記
單根繼承結(jié)構(gòu)
在單根繼承結(jié)構(gòu)中所有的對(duì)象都具有一個(gè)共用接口侍筛,所以它們歸根到底都是相同的基本類(lèi)型萤皂。
單根繼承結(jié)構(gòu)保證所有對(duì)象都具備某些功能。
單根繼承結(jié)構(gòu)使垃圾回收器的實(shí)現(xiàn)變得容易得多勾笆,而垃圾回收器正是Java相對(duì)C++的重要改進(jìn)之一敌蚜。由于所有對(duì)象都保證具有其類(lèi)型信息,因此不會(huì)因無(wú)法確定對(duì)象的類(lèi)型而陷入僵局窝爪。這對(duì)于系統(tǒng)級(jí)操作顯得尤其重要弛车,并且給編程帶來(lái)了更大的靈活性。
容器
如果不知道在解決某個(gè)特定問(wèn)題時(shí)需要多少個(gè)對(duì)象蒲每,或者它們將存活多久纷跛,那么久不可能知道如何存儲(chǔ)這些對(duì)象。這類(lèi)信息只有在運(yùn)行時(shí)才能獲得邀杏。
這個(gè)通常被稱為容器的新對(duì)象贫奠,在任何需要時(shí)都可擴(kuò)充自己唬血,以容納你置于其中的所有東西。因此不需要知道將來(lái)會(huì)把多少個(gè)對(duì)象置于容器中唤崭,只需要?jiǎng)?chuàng)建一個(gè)容器對(duì)象拷恨,然后讓它處理所有細(xì)節(jié)。
Java在其標(biāo)準(zhǔn)類(lèi)庫(kù)中包含有大量的容器谢肾。在Java中腕侄,有滿足不同需要的各種類(lèi)型的容器,例如List芦疏,Map冕杠,Set,以及諸如隊(duì)列酸茴、樹(shù)分预、堆棧等更多的構(gòu)件。
需要對(duì)容器有所選擇薪捍,這有兩個(gè)原因:
- 第一笼痹,不同容器提供了不同類(lèi)型的接口和外部行為。
- 第二飘诗,不同的容器對(duì)于某些操作具有不同的效率与倡。
參數(shù)化類(lèi)型
創(chuàng)建這樣的容器,它知道自己所保存的對(duì)象的類(lèi)型昆稿,從而不需要向下轉(zhuǎn)型以及消除犯錯(cuò)誤的可能性纺座,這種解決方案被稱為參數(shù)化類(lèi)型機(jī)制。
參數(shù)化類(lèi)型就是一個(gè)編譯器可以自動(dòng)定制作用于特定類(lèi)型上的類(lèi)溉潭。
參數(shù)化類(lèi)型净响,在Java中它稱為范型。一堆尖括號(hào)喳瓣,中間包含類(lèi)型信息馋贤,通過(guò)這些特征就可以識(shí)別對(duì)范型的使用。
例如畏陕,創(chuàng)建一個(gè)存儲(chǔ)Shape的ArrayList:
ArrayList<Shape> shapes = new ArrayList<Shape>();
對(duì)象的創(chuàng)建和生命期
怎樣才能知道何時(shí)銷(xiāo)毀這些對(duì)象呢配乓?當(dāng)處理完某個(gè)對(duì)象之后,系統(tǒng)其他部分可能還在處理它惠毁。
在被稱為堆(heap)的內(nèi)存池中動(dòng)態(tài)地創(chuàng)建對(duì)象犹芹。在這種方式中,直到運(yùn)行時(shí)才知道需要多少對(duì)象鞠绰,它們的生命周期如何腰埂,以及它們的具體類(lèi)型是什么。如果需要一個(gè)新對(duì)象蜈膨,可以在需要的時(shí)刻直接在堆中創(chuàng)建屿笼。因?yàn)榇鎯?chǔ)空間是在運(yùn)行時(shí)被動(dòng)態(tài)管理的牺荠,所以需要大量的時(shí)間在堆中分配空間。
動(dòng)態(tài)方式有這樣一個(gè)一般性的邏輯假設(shè):對(duì)象趨于變得復(fù)雜驴一,所以查找和釋放存儲(chǔ)空間的開(kāi)銷(xiāo)不會(huì)對(duì)對(duì)象的創(chuàng)建造成重大沖擊休雌。
Java完全采用了動(dòng)態(tài)內(nèi)存分配方式。
生命周期蛔趴。對(duì)于允許在堆棧上創(chuàng)建對(duì)象的語(yǔ)言挑辆,編譯器可以確定對(duì)象存活的時(shí)間,并可以自動(dòng)銷(xiāo)毀它孝情。如果是在堆上創(chuàng)建對(duì)象,編譯器就會(huì)對(duì)它的生命周期一無(wú)所知洒嗤。Java提供了“垃圾回收”的機(jī)制箫荡,自動(dòng)發(fā)現(xiàn)對(duì)象何時(shí)不再被使用,并繼而銷(xiāo)毀它渔隶。垃圾回收器提供了更高層的保障羔挡,可以避免暗藏的內(nèi)存泄漏問(wèn)題。
異常處理:處理錯(cuò)誤
Java一開(kāi)始就內(nèi)置了異常處理间唉,而且強(qiáng)制你必須使用它绞灼。它是唯一可接受的錯(cuò)誤報(bào)告方式。這種有保障的一致性有時(shí)會(huì)使得錯(cuò)誤處理非常容易呈野。
異常處理不是面向?qū)ο蟮奶卣鳌M管在面向?qū)ο笳Z(yǔ)言中低矮,異常常常被表示稱為一個(gè)對(duì)象。
并發(fā)編程
共享資源被冒。如果有多個(gè)并行任務(wù)都要訪問(wèn)統(tǒng)一資源军掂,那么就會(huì)出問(wèn)題。為了解決這個(gè)問(wèn)題昨悼,整個(gè)過(guò)程是:某個(gè)任務(wù)鎖定某項(xiàng)資源蝗锥,完成其任務(wù),然后釋放資源鎖率触,使其他任務(wù)可以使用這項(xiàng)資源终议。
Java的并發(fā)是內(nèi)置于語(yǔ)言中的。
Java與Internet
Java解決了在萬(wàn)維網(wǎng)上的程序設(shè)計(jì)問(wèn)題葱蝗。
Web是什么
- 客戶/服務(wù)器計(jì)算技術(shù)穴张。
客戶/服務(wù)器系統(tǒng)的核心思想是:系統(tǒng)具有一個(gè)中央信息存儲(chǔ)池,用來(lái)存儲(chǔ)某種數(shù)據(jù)垒玲,通常存在于數(shù)據(jù)庫(kù)中陆馁,可以根據(jù)需要將它分發(fā)給某些人員或者機(jī)器集群。信息存儲(chǔ)池合愈、用于分發(fā)信息的軟件以及信息與軟件所駐留的機(jī)器或機(jī)群被總稱為服務(wù)器叮贩。駐留在用戶機(jī)器上的軟件與服務(wù)器進(jìn)行通信击狮,以獲取信息、處理信息益老,然后將他們先是在被稱為客戶機(jī)的用戶機(jī)器上彪蓬。
基本概念并不復(fù)雜。問(wèn)題是單一的服務(wù)器捺萌,要同時(shí)為多個(gè)客戶服務(wù)档冬。因此設(shè)計(jì)者把數(shù)據(jù)“均衡”分布于數(shù)據(jù)表中,以取得最優(yōu)的使用效果桃纯。此外酷誓,必須保證一個(gè)客戶插入的新數(shù)據(jù)不會(huì)覆蓋另一個(gè)客戶插入的新數(shù)據(jù),也不會(huì)在將其添加到數(shù)據(jù)庫(kù)的過(guò)程中丟失(這被稱為事務(wù)處理)态坦。還有一個(gè)重要的性能問(wèn)題盐数,可能任意時(shí)刻都有成百上千的客戶向服務(wù)器發(fā)出請(qǐng)求,為了將延遲最小火伞梯,程序員努力減輕處理任務(wù)的負(fù)載玫氢,通常是分散給客戶端機(jī)器處理,但有時(shí)也會(huì)使用所謂的中間件將負(fù)載分散給在服務(wù)器端的其他機(jī)器谜诫。
分發(fā)信息這個(gè)簡(jiǎn)單思想的復(fù)雜性實(shí)際上是有很多不同層次的漾峡,它至關(guān)重要。
- Web就是一臺(tái)巨型服務(wù)器喻旷。
所有的服務(wù)器和客戶機(jī)都同時(shí)共存于同一個(gè)網(wǎng)絡(luò)中生逸。
瀏覽器只是一個(gè)觀察器,它甚至不能執(zhí)行最簡(jiǎn)單的計(jì)算任務(wù)掰邢。引入在客戶端瀏覽器中運(yùn)行程序的能力牺陶,這被稱為“客戶端編程”。
客戶端編程
Web最初的“服務(wù)器-瀏覽器”設(shè)計(jì)師為了能夠提供交互性的內(nèi)容辣之,其交互性完全由服務(wù)器提供掰伸。
基本的HTML包含有簡(jiǎn)單的數(shù)據(jù)收集機(jī)制,收集來(lái)的數(shù)據(jù)怀估,利用按鈕的提交動(dòng)作狮鸭,通過(guò)所有的Web服務(wù)器都提供的通用網(wǎng)關(guān)接口(CGI)傳遞。
構(gòu)建于CGI程序之上的網(wǎng)站可能會(huì)迅速變得過(guò)于復(fù)雜而難以維護(hù)多搀,同時(shí)產(chǎn)生響應(yīng)時(shí)間過(guò)長(zhǎng)的問(wèn)題歧蕉。CGI程序的響應(yīng)時(shí)間依賴于所必須發(fā)送的數(shù)據(jù)量的大小,以及服務(wù)器和Internet的負(fù)載康铭。
比如惯退,你肯定經(jīng)歷過(guò)對(duì)Web輸入表單進(jìn)行數(shù)據(jù)驗(yàn)證的過(guò)程:按下提交按鈕,數(shù)據(jù)發(fā)送到服務(wù)器从藤,服務(wù)器啟動(dòng)CGI腳本檢查催跪,發(fā)現(xiàn)錯(cuò)誤锁蠕,將錯(cuò)誤組裝為一個(gè)html頁(yè)面發(fā)送給你,之后你必須匯推一個(gè)頁(yè)面懊蒸,然后再試荣倾。
問(wèn)題的解決方案就是客戶端編程。意味著Web瀏覽器能用來(lái)執(zhí)行任何它可以完成的工作骑丸,使得返回給用戶的結(jié)果更加迅捷舌仍。
客戶端編程的問(wèn)題是:它與通常意義上的編程十分不同。Web瀏覽器就像一個(gè)功能受限的操作系統(tǒng)通危。
- 插件
插件對(duì)于客戶端編程的價(jià)值在于:允許專(zhuān)家級(jí)的程序員不需經(jīng)過(guò)瀏覽器生產(chǎn)廠商的許可铸豁,就可以開(kāi)發(fā)某種語(yǔ)言擴(kuò)展,并將它們添加到服務(wù)器中黄鳍。
2.腳本語(yǔ)言
插件引發(fā)了瀏覽器腳本語(yǔ)言的開(kāi)發(fā)推姻。缺點(diǎn)是代碼會(huì)暴露給任何人去瀏覽。
在Web瀏覽器內(nèi)部使用的腳本語(yǔ)言實(shí)際上總是被用來(lái)解決特定類(lèi)型的問(wèn)題框沟,主要是用來(lái)創(chuàng)建更豐富、更具有交互性的圖形化用戶界面增炭。腳本語(yǔ)言可以解決客戶端編程中所遇到的80%的問(wèn)題忍燥。
- Java
那么剩下的20%呢?Java是處理他們最流行的解決方案隙姿。
Java是通過(guò)applet以及使用Java Web Start來(lái)進(jìn)行客戶端編程的梅垄。
applet是只在Web瀏覽器中運(yùn)行的小程序,是作為網(wǎng)頁(yè)的一部分而自動(dòng)下載的输玷。當(dāng)applet被激活時(shí)队丝,它便開(kāi)始執(zhí)行一個(gè)程序。它提供一種分發(fā)軟件的方法欲鹏,一旦用戶需要客戶端軟件時(shí)机久,就自動(dòng)從服務(wù)器把客戶端軟件分發(fā)給用戶。
- 備選方案
這里提到了Flex技術(shù)赔嚎。由于本書(shū)出版于2007年膘盖,某些當(dāng)時(shí)的新技術(shù)可能有些過(guò)時(shí),或許后來(lái)又出現(xiàn)了更好的技術(shù)尤误。筆記僅根據(jù)本書(shū)而作侠畔,不做更多的擴(kuò)展。
- .NET和C#
同樣损晤,這部分內(nèi)容具有時(shí)效性软棺。不多說(shuō)明。
- Internet與Intranet
Web是最常用的解決客戶/服務(wù)器問(wèn)題的方案尤勋。對(duì)于公司內(nèi)部典型的客戶/服務(wù)器問(wèn)題喘落,也一樣可以使用這項(xiàng)技術(shù)茵宪。
如果程序運(yùn)行與Intranet上,那么可能會(huì)受到不同的限制揖盘。就和Internet的情況不一樣了眉厨。
面對(duì)各種解決客戶端編程問(wèn)題的方案時(shí),首先需要進(jìn)行性價(jià)比分析兽狭,認(rèn)真考慮問(wèn)題的各種限制憾股,然后思考哪種解決方案可以成為最短的捷徑。
服務(wù)器端編程
這部分主要在企業(yè)Java編程思想中進(jìn)行論述箕慧。
總結(jié)
過(guò)程型語(yǔ)言:數(shù)據(jù)定義和函數(shù)調(diào)用服球。你需要通讀函數(shù)調(diào)用和低層概念,以在腦海里建立一個(gè)模型颠焦。這些程序使用的表示術(shù)語(yǔ)更加面向計(jì)算機(jī)而不是你要解決的問(wèn)題斩熊。
編寫(xiě)良好的Java程序通常比過(guò)程型程序要簡(jiǎn)單的多,而且也易于理解的多伐庭。
OOP和Java也許并不適合所有的人粉渠。重要的是正確評(píng)估自己的需求。