141、繼承(inheritance)的優(yōu)缺點(diǎn)是什么?
● 優(yōu)點(diǎn):
新的實(shí)現(xiàn)很容易,因?yàn)榇蟛糠质抢^承而來(lái)的。很容易修改和擴(kuò)展已有的實(shí)現(xiàn)。
● 缺點(diǎn):
打破了封裝,因?yàn)榛?lèi)向子類(lèi)暴露了實(shí)現(xiàn)細(xì)節(jié),白盒重用,因?yàn)榛?lèi)的內(nèi)部細(xì)節(jié)通常對(duì)子類(lèi)是可見(jiàn)的,當(dāng)父類(lèi)的實(shí)現(xiàn)改變時(shí)可能要相應(yīng)的對(duì)子類(lèi)做出改變,不能在運(yùn)行時(shí)改變由父類(lèi)繼承來(lái)的實(shí)現(xiàn)。由此可見(jiàn),組合比繼承具有更大的靈活性和更穩(wěn)定的結(jié)構(gòu),一般情況下應(yīng)該優(yōu)先考慮組合。只有當(dāng)下列條件滿(mǎn)足時(shí)才考慮使用繼承:子類(lèi)是一種特殊的類(lèi)型,而不只是父類(lèi)的一個(gè)角色,子類(lèi)的實(shí)例不需要變成另一個(gè)類(lèi)的對(duì)象子類(lèi)擴(kuò)展,而不是覆蓋或者使父類(lèi)的功能失效。
Java接口和Java抽象類(lèi)代表的就是抽象類(lèi)型,就是我們需要提出的抽象層的具體表現(xiàn)。OOP面向?qū)ο蟮木幊?,如果要提高程序的?fù)用率,增加程序的可維護(hù)性,可擴(kuò)展性,就必須是面向接口的編程,面向抽象的編程。
● Java接口和Java抽象類(lèi)最大的一個(gè)區(qū)別,就在于Java抽象類(lèi)可以提供某些方法的部分實(shí)現(xiàn),而Java接口不可以,這大概就是Java抽象類(lèi)唯一的優(yōu)點(diǎn)吧,但這個(gè)優(yōu)點(diǎn)非常有用。 如果向一個(gè)抽象類(lèi)里加入一個(gè)新的具體方法時(shí),那么它所有的子類(lèi)都一下子得到了這個(gè)新方法,而Java接口做不到這一點(diǎn),如果向一個(gè)Java接口里加入一個(gè)新方法,所有實(shí)現(xiàn)這個(gè)接口的類(lèi)就無(wú)法成功通過(guò)編譯了,因?yàn)槟惚仨氉屆恳粋€(gè)類(lèi)都再實(shí)現(xiàn)這個(gè)方法才行。
● 一個(gè)抽象類(lèi)的實(shí)現(xiàn)只能由這個(gè)抽象類(lèi)的子類(lèi)給出,也就是說(shuō),這個(gè)實(shí)現(xiàn)處在抽象類(lèi)所定義出的繼承的等級(jí)結(jié)構(gòu)中,而由于Java語(yǔ)言的單繼承性,所以抽象類(lèi)作為類(lèi)型定義工具的效能大打折扣。在這一點(diǎn)上,Java接口的優(yōu)勢(shì)就出來(lái)了,任何實(shí)現(xiàn)了一個(gè)Java接口所規(guī)定的方法的類(lèi)都可以具有這個(gè)接口的類(lèi)型,而一個(gè)類(lèi)可以實(shí)現(xiàn)任意多個(gè)Java接口,從而這個(gè)類(lèi)就有了多種類(lèi)型。Java接口是定義混合類(lèi)型的理想工具,混合類(lèi)表明一個(gè)類(lèi)不僅僅具有某個(gè)主類(lèi)型的行為,而且具有其他的次要行為。
● 結(jié)合以上描述中抽象類(lèi)和Java接口的各自?xún)?yōu)勢(shì),精典的設(shè)計(jì)模式就出來(lái)了:聲明類(lèi)型的工作仍然由Java接口承擔(dān),但是同時(shí)給出一個(gè)Java抽象類(lèi),且實(shí)現(xiàn)了這個(gè)接口,而其他同屬于這個(gè)抽象類(lèi)型的具體類(lèi)可以選擇實(shí)現(xiàn)這個(gè)Java接口,也可以選擇繼承這個(gè)抽象類(lèi),也就是說(shuō)在層次結(jié)構(gòu)中,Java接口在最上面,然后緊跟著抽象類(lèi)。這下兩個(gè)的最大優(yōu)點(diǎn)都能發(fā)揮到極至了。這個(gè)模式就是“缺省適配模式”。在Java語(yǔ)言API中用了這種模式,而且全都遵循一定的命名規(guī)范:Abstract+接口名。
Java接口和Java抽象類(lèi)的存在就是為了用于具體類(lèi)的實(shí)現(xiàn)和繼承的,如果你準(zhǔn)備寫(xiě)一個(gè)具體類(lèi)去繼承另一個(gè)具體類(lèi)的話(huà),那你的設(shè)計(jì)就有很大問(wèn)題了。Java抽象類(lèi)就是為了繼承而存在的,它的抽象方法就是為了強(qiáng)制子類(lèi)必須去實(shí)現(xiàn)的。
使用Java接口和抽象Java類(lèi)進(jìn)行變量的類(lèi)型聲明、參數(shù)的類(lèi)型聲明、方法的返回類(lèi)型說(shuō)明,以及數(shù)據(jù)類(lèi)型的轉(zhuǎn)換等。而不要用具體Java類(lèi)進(jìn)行變量的類(lèi)型聲明、參數(shù)類(lèi)型聲明、方法的返回類(lèi)型說(shuō)明,以及數(shù)據(jù)類(lèi)型的轉(zhuǎn)換等。如果你寫(xiě)的代碼里面連一個(gè)接口和抽象類(lèi)都沒(méi)有的話(huà),也許我可以說(shuō)你根本沒(méi)有用到任何設(shè)計(jì)模式,任何一個(gè)設(shè)計(jì)模式都是和抽象分不開(kāi)的,而抽象與Java接口和抽象Java類(lèi)又是分不開(kāi)的。
接口的作用,就是標(biāo)識(shí)類(lèi)的類(lèi)別。把不同類(lèi)型的類(lèi)歸于不同的接口,可以更好的管理他們。把一組看如不相關(guān)的類(lèi)歸為一個(gè)接口去調(diào)用??梢杂靡粋€(gè)接口型的變量來(lái)引用一個(gè)對(duì)象。
持久化的對(duì)象,是已經(jīng)存儲(chǔ)到數(shù)據(jù)庫(kù)或保存到本地硬盤(pán)中的對(duì)象,我們稱(chēng)之為持久化對(duì)象。為了保存在內(nèi)存中的各種對(duì)象的狀態(tài)(也就是實(shí)例變量,不是方法),并且可以把保存的對(duì)象狀態(tài)再讀出來(lái)。我們可以使用Java提供的序列化機(jī)制。
簡(jiǎn)單說(shuō)對(duì)象序列化是將對(duì)象狀態(tài)轉(zhuǎn)換為可保持或傳輸?shù)母袷降倪^(guò)程。什么情況下需要序列化:
● 當(dāng)你想把的內(nèi)存中的對(duì)象狀態(tài)保存到一個(gè)文件中或者數(shù)據(jù)庫(kù)中時(shí)候;
● 當(dāng)你想用套接字在網(wǎng)絡(luò)上傳送對(duì)象的時(shí)候;
● 當(dāng)你想通過(guò)RMI傳輸對(duì)象的時(shí)候;
對(duì)象要實(shí)現(xiàn)序列化,是非常簡(jiǎn)單的,只需要實(shí)現(xiàn)Serializable接口就可以了。
● javascript的優(yōu)點(diǎn):
javascript 減少網(wǎng)絡(luò)傳輸:在javascript這樣的用戶(hù)端腳本語(yǔ)言出現(xiàn)之前,傳統(tǒng)的數(shù)據(jù)提交和驗(yàn)證工作均由用戶(hù)端瀏覽器通過(guò)網(wǎng)絡(luò)傳輸?shù)椒?wù)器開(kāi)發(fā)上進(jìn)行。如果數(shù)據(jù)量很大,這對(duì)于網(wǎng)絡(luò)和服務(wù)器開(kāi)發(fā)的資源來(lái)說(shuō)實(shí)在是一種無(wú)形的浪費(fèi)。而使用javascript就可以在客戶(hù)端進(jìn)行數(shù)據(jù)驗(yàn)證。
javascript方便操縱html對(duì)象:javascript可以方便地操縱各種頁(yè)面中的對(duì)象,用戶(hù)可以使用javascript來(lái)控制頁(yè)面中各個(gè)元素的外觀、狀態(tài)甚至運(yùn)行方式,javascript可以根據(jù)用戶(hù)的需要“定制”瀏覽器,從而使網(wǎng)頁(yè)更加友好。
javascript支持分布式應(yīng)用運(yùn)算:javascript可以使多種任務(wù)僅在用戶(hù)端就可以完成,而不需要網(wǎng)絡(luò)和服務(wù)器開(kāi)發(fā)的參與,從而支持分布式應(yīng)用的運(yùn)算和處理。
● javascript的局限性:
各瀏覽器廠商對(duì)javascript支持程度不同:目前在互聯(lián)網(wǎng)上有很多瀏覽器,如firefox、internet explorer、opera等,但每種瀏覽器支持javascript的程度是不一樣的,不同的瀏覽器在瀏覽一個(gè)帶有javascript腳本的主頁(yè)時(shí),由于對(duì)javascript的支持稍有不同,其效果會(huì)有一定的差距,有時(shí)甚至?xí)@示不出來(lái)。
“web 安全性”對(duì)javascript一些功能犧牲:當(dāng)把javascript的一個(gè)設(shè)計(jì)目標(biāo)設(shè)定為“web安全性”時(shí),就需要犧牲javascript的一些功能。因此,純粹的javascript將不能打開(kāi)、讀寫(xiě)和保存用戶(hù)計(jì)算機(jī)上的文件。其有權(quán)訪問(wèn)的唯一信息就是該javascript所嵌入開(kāi)發(fā)的那個(gè)web主頁(yè)中的信息,簡(jiǎn)言之,javascript將只存在于它自己的小小世界—web主頁(yè)里。
JSP(Java Server Pages)是由Sun Microsystems公司倡導(dǎo)、許多公司參與一起建立的一種動(dòng)態(tài)網(wǎng)頁(yè)技術(shù)標(biāo)準(zhǔn)
JSP 技術(shù)是用JAVA語(yǔ)言作為腳本語(yǔ)言的,JSP網(wǎng)頁(yè)為整個(gè)服務(wù)器端的JAVA庫(kù)單元提供了一個(gè)接口來(lái)服務(wù)于HTTP的應(yīng)用程序。
在傳統(tǒng)的網(wǎng)頁(yè)HTML文件(*.htm,*.html)中加入Java程序片段(Scriptlet)和JSP標(biāo)記(tag),就構(gòu)成了JSP網(wǎng)頁(yè)(*.jsp)。Web服務(wù)器在遇到訪問(wèn)JSP網(wǎng)頁(yè)的請(qǐng)求時(shí),首先執(zhí)行其中的程序片段,然后將執(zhí)行結(jié)果以HTML格式返回給客戶(hù)。程序片段可以操作數(shù)據(jù)庫(kù)、重新定向網(wǎng)頁(yè)以及發(fā)送email等等,這就是建立動(dòng)態(tài)網(wǎng)站所需要的功能。所有程序操作都在服務(wù)器端執(zhí)行,網(wǎng)絡(luò)上傳送給客戶(hù)端的僅是得到的結(jié)果,對(duì)客戶(hù)瀏覽器的要求最低,可以實(shí)現(xiàn)無(wú)Plugin,無(wú)ActiveX,無(wú) Java Applet,甚至無(wú)Frame。
● JSP 的優(yōu)點(diǎn):
對(duì)于用戶(hù)界面的更新,其實(shí)就是由Web Server進(jìn)行的,所以給人的感覺(jué)更新很快。
所有的應(yīng)用都是基于服務(wù)器的,所以它們可以時(shí)刻保持最新版本。
客戶(hù)端的接口不是很繁瑣,對(duì)于各種應(yīng)用易于部署、維護(hù)和修改。
臟數(shù)據(jù)在臨時(shí)更新(臟讀)中產(chǎn)生。事務(wù)A更新了某個(gè)數(shù)據(jù)項(xiàng)X,但是由于某種原因,事務(wù)A出現(xiàn)了問(wèn)題,于是要把A回滾。但是在回滾之前,另一個(gè)事務(wù)B讀取了數(shù)據(jù)項(xiàng)X的值(A 更新后),A回滾了事務(wù),數(shù)據(jù)項(xiàng)恢復(fù)了原值。事務(wù)B讀取的就是數(shù)據(jù)項(xiàng)X的就是一個(gè)“臨時(shí)”的值,就是臟數(shù)據(jù)。
臟讀就是指當(dāng)一個(gè)事務(wù)正在訪問(wèn)數(shù)據(jù),并且對(duì)數(shù)據(jù)進(jìn)行了修改,而這種修改還沒(méi)有提交到數(shù)據(jù)庫(kù)中,這時(shí),另外一個(gè)事務(wù)也訪問(wèn)這個(gè)數(shù)據(jù),然后使用了這個(gè)數(shù)據(jù)。因?yàn)檫@個(gè)數(shù)據(jù)是還沒(méi)有提交的數(shù)據(jù),那么另外一個(gè)事務(wù)讀到的這個(gè)數(shù)據(jù)是臟數(shù)據(jù),依據(jù)臟數(shù)據(jù)所做的操作可能是不正確的。