




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、設(shè)計(jì)API時(shí)要區(qū)分其目標(biāo)用戶群,8,第八 章,插件、客戶端程序的區(qū)別: 插件:插件是一種遵循一定規(guī)范的應(yīng)用程序接口編寫出來的程序。很多軟件都有插件,插件有無數(shù)種。例如在IE中,安裝相關(guān)的插件后,WEB瀏覽器能夠直接調(diào)用插件程序,用于處理特定類型的文件。 客戶端程序:客戶服務(wù)(Customer Service),是指一種以客戶為導(dǎo)向的價(jià)值觀,它整合及管理在預(yù)先設(shè)定的最優(yōu)成本服務(wù)組合中的客戶界面的所有要素。廣義而言,任何能提高客戶滿意度的內(nèi)容都屬于客戶服務(wù)的范圍之內(nèi)。,一些程序功能不僅可以直接通過界面進(jìn)行操作,還可以提供相應(yīng)的API,以供其他程序來調(diào)用,這樣第三方程序可以發(fā)起通訊,使用相應(yīng)程序的A
2、PI指使它完成操作,命令執(zhí)行完后,控制權(quán)返回給調(diào)用者。 XMMS的API還提供插件支持,第三方可發(fā)商可以通過注冊(cè)“輸出插件”來擴(kuò)展XMMS的功能。它與前面說的客戶端的地位完全不同。,第三方的播放場(chǎng),SPI組成:是與前面說的客戶端的地位完全不同。它沒有讓XMMS進(jìn)行任何操作。但它為XMMS增加了很多功能,所以此時(shí)的插件不是前文所說的“客戶端”。XMMS的這種注冊(cè)插件來擴(kuò)展功能的方式是SPI(Service Provider Interface)的典型應(yīng)用。,Service Provider Interface,為了說明客戶端API和SPI區(qū)別, Void xmms_play();Void xmm
3、s_pause(); Void xmms_add_to_list(char *); 使用Java語言來定義API的方式則完全不同。 Public class XMMS Public void play() doPlay(); Public void pause() doPause(); Public void addToPlaylist(String file) do addToPlaylist(file); ,8.1 C和Java語言中如何定義API和SPI(1),C和Java語言中如何定義API和SPI(2),在Java中聲明API方式有多種。如說可使用static方法、實(shí)例方法、抽象方法
4、、以及final方法,這些都是可以的。但編寫一個(gè)SPI,情況就不同。 如果要使用C語言來為XMMS編寫程序一個(gè)插件的話,必須要寫一個(gè)支持回放的函數(shù),代碼如下: Void my_playbackprints(char *text) Printf(“%sn”,text); Interface Playback Public void playback(byte data); Class MyCallbackPrints implements XMMS.Playback Public void playback (byte data) System.out.println(new String(da
5、ta); Xmms.registerPlayback(new MyCallbackPrints();,C和Java語言中如何定義API和SPI(3),對(duì)于Java程序員,只要所編寫的方法不是private、final或者static的,那么就表示該是方法支持調(diào)的,而且可以用看成是一個(gè)API。對(duì)很多程序員,甚至是教師都沒有清楚地理解這一點(diǎn),它也的確不是日常編碼的內(nèi)容。,8.2 API演進(jìn)不同于SPI演進(jìn)(1),具體的演進(jìn)方案則還是取決于具體的接口類型:向API中添加一些內(nèi)容總是可以的,但要移除一些內(nèi)容則不行。 但對(duì)于SPI,移除一些內(nèi)容可以允許,但不允許添加新的內(nèi)容。建立契約時(shí),必須清楚地區(qū)分哪
6、些是API,提供給外面調(diào)用,而哪些是SPI,用來讓外部來擴(kuò)展程序功能。設(shè)計(jì)時(shí)容易犯的最大錯(cuò)誤就是將API和SPI混在一個(gè)類里。根據(jù)SPI的契約,不能添加方法,根據(jù)API的契約,也不能減少方法。,8.3 java.io.Write 這個(gè)類從JDK1.4到JDK5的演進(jìn),還需要使用try/catch/finally的方式來進(jìn)行防御性編碼。 Try bufferedWrite.append(what); catch (UnsupportedOpeartionException ex ) bufferedWrite.write(what.toString(); 這樣來調(diào)用API的確有點(diǎn)怪。調(diào)用一個(gè)方法
7、竟然要寫四行代碼,java.io.Write 的演進(jìn)(2),假設(shè)已有一個(gè)優(yōu)化過Write類,它無須將數(shù)據(jù)轉(zhuǎn)換成字符串,而是直接處理以提高性能,但用戶卻可能無法用到這種夢(mèng)寐以求的優(yōu)化, Public class CountingWrite extends Write Private int counter; Public int getcharacterCount() Return counter; ,java.io.Write 的演進(jìn)(3),Override Public void write(char cbuf ,int off,int len) throws IoException Cou
8、nter+=len; Override Public Write append(CharSepuence csq) throws IoException Counter +=csq.length(); Return this ; 。,Private static final class CDSequence implements CharSequence Private final int start;Private final int end; Public CDSequence() This(0,647*1024*1024); Private CDSequence(int start,in
9、t end) This.start=start; This.end=end; Public int length() Return end-start; CountingWriter writer=new CountingWriter(); CDSequence cdImage=new CDSequence(); BufferedWriter bufferedWriter=new BufferedWriter(writer); bufferedWriter.append(cdImage); assertEquals( “Correct number of writes delegated”,
10、cdImage.length(),writer.getCharacterCount();,從JDK1.4到JDK5的演進(jìn)(4),這個(gè)通過覆蓋來優(yōu)化性能的方法卻不會(huì)被調(diào)用,效率仍然沒有提高。 If (shouldBufferAs TheSequenceIsNotTooBig(csq) Write(csq.toString(); else Flush();Out.append(csq); Return this;,從JDK1.4到JDK5的演進(jìn)(5),首先計(jì)算一下字符的數(shù)量,如果數(shù)量比較小,性能影響也比較小,就使用老的方式處理,否則就先寫入當(dāng)前數(shù)據(jù)后,再寫入大數(shù)據(jù)。然而,還遠(yuǎn)遠(yuǎn)沒有結(jié)束,還有一個(gè)潛
11、在的問題需要解決。 Public class CryptoWriter extends BufferedWriter Public CryptoWriter(Writer out) Super(out); Override Public void write(char buf,int off,int len) throws IoException Char arr=new charlen; For (int i=0;ilen;i+) Arri=encryptChar(bufoff+i); Super.write(arr,0,len);,從JDK1.4到JDK5的演進(jìn)(6),Override P
12、ublic void write(int c) throws IoException Super.write(encryptChar); override Public void write(String str,int off,int len) throws IoException StringBuffer sb=new StringBuffer(); For (int i+0;ilen;I+) Sb.append(encryptChar(str.charAt(off+i); Super.write(sb.toString(),0,len); Private char encryptChar
13、(int c) If (c=Z) Return A; If (c=z) Return a; Return (char)(c+1); 。,從JDK1.4到JDK5的演進(jìn)(7),事情變得越來越復(fù)雜了!為了處理含有大量字符串的對(duì)象等目的,最好是直接將數(shù)據(jù)寫入相應(yīng)的Writer對(duì)象。 Boolean isOverriden =false; Try isOverriden=( getClas().getMethod( “write”,String.class ).getDeclaringClass()!=Writer.class)| (getClass().getMethod( “write”,inte
14、ger.TYPE ).getDeclaringClass !=BufferedWriter.class)| ( getClass().getMethod( “write”,String.class,Integer.TYPE,Integer.TYPE ).getDeclaringClass()!=BufferedWriter.class ); catch (Exception ex) Throws new IoException(ex); If (isOverriden |shouldBufferAsTheSequenceIsNotTooBig(csq) Write(csq.toString()
15、; else Flush(); Out.append(csq); Return this;,反射技術(shù),第三個(gè)版本才是最終的解決方案。它使用了反射技術(shù),所以看起來復(fù)雜一點(diǎn),但卻是一個(gè)非常有效的解決方案。 反射技術(shù)讓這段代碼看起來不如原來那么漂亮了,但至少它可以正常運(yùn)行,結(jié)果也是正確的。 讓一個(gè)類可以被動(dòng)繼承,其實(shí)就意味著把它當(dāng)作一個(gè)SPI,因?yàn)槠渥宇惪梢蕴峁残录夹g(shù)部的功能,或者說新的服務(wù),但對(duì)于代理來說,它更多是讓其它的代碼來進(jìn)行調(diào)用它的功能,屬于功能API,兩者是不一樣。不能像表面看起來那么簡(jiǎn)單、順暢了。,如何避免繼承(1),Public final class Writer Private
16、final Impl impl ; Private Writer(Impl,impl) This.impl=impl; Public final void write(int c) throws IoException Char arr= (char) c ; Impl.write(arr,0,1); Public final void write(char cbuf) thrpws IoException Impl.write(cbuf,0,cbuf.length); Public final void write(char cbuf,int off,int len ) Throws IoE
17、xception Impl.write(cbuf ,off,len); Public final void write(String str) throws IoException Impl.write(str,0,str.length(); ,如何避免繼承(2),Public final void write(String str ,int off,int len) Throws IoException Impl.write(str,off,len); Public final void flush() throws IoException Impl.flush(); Public fina
18、l void close() throws IoException Impl.close();,SPI的提供者類(1),現(xiàn)在寫一個(gè)SPI的提供者類,這個(gè)類中全部都是工廠方法,用來提供Impl接口的具體實(shí)現(xiàn),基本上就是下面這個(gè)樣子。 Public static Writercreat(Impl impl ) Return new Writer(impl); Public static Writer creat(final java.io.Writer w) Return new Writer(new Impl() Public void Write(String,str,int off,int
19、len ) Throws IoException w.Write(str,off,len);,SPI的提供者類(2),Public void write(char arr,int off,int len ) Throws IoException w.write(arr,off,len); Public void close() throws IoExcepton w.close(); Public void flush() throws IoException w.flush(); Public static Writer creatBuffered(final Writer out) Ret
20、urn create(new SimpleBuffer(out); Public static interface Impl Public void close() throws IoException; Public void flush() throws IoException ; Public void write(String s,int off,int len) throws IoException; Public void write(char a,int off,int len) throws IoException;,SPI的提供者類(3),Public final class
21、 Writer implements Appendable Private final Impl impl ; Private final ImplSeq seq; Private Writer(Impl impl ,ImplSeq seq) This.impl =impl; Thisseq =seq; Public final void write(int c) throws IException If (impl!=null) Char arr =(char) c; Impl.write(arr ,0,1) else Seq.write(new CharSeq(c); Public fin
22、al void write(char cbuf) throws IoException If (impl!=null) Impl.write(cbuf,0,cbuf.length); elseSeq.write(new CharSeq(cbuf,0,cbuf.length); ,SPI的提供者類(4),Public final void write(char cbuf,int off,int len) Throws IoException If (impl! =null) Impl.write(cbuf,off,len); else Seq.write(new CharSeq(cbuf,off
23、,len); Public final void write(String str) throws IoException If (impl! =null) Impl.write(str,0,str.length); else Seq.write(str); Public final void write(String str,int off,int len) Throws IoException If (impl!=null) Impl.write(str,off,len); else Seq.write(str.subSequence(off,off+len); ,SPI的提供者類(5),
24、Public final void flush() throws IoException If (impl!=null) Impl.flush(); else Seq.flush(); Public final void close() throws IoException If (impl!=null) Impl.close(); else Seq.flush(); ,SPI的提供者類(6),設(shè)計(jì)給客戶使用API,最好用final類;而設(shè)計(jì)SPI的時(shí)候,則最好用接口,然后 通過一個(gè)工廠模式將它們結(jié)合在一起。借助“工廠設(shè)計(jì)模式”盡可能是對(duì)客戶“隱藏了”相應(yīng)的復(fù)雜度,在API功能時(shí),用戶則只看到final類Writer,對(duì)于要擴(kuò)展API功能的人,則只需要看到兩個(gè)要實(shí)現(xiàn)的接口Impl和ImplSeq,所以不管是使用還是擴(kuò)展這個(gè)API,復(fù)雜度都不高。雖然根據(jù)這個(gè)方案寫出第一個(gè)版本API時(shí),也許工作量會(huì)多一些,但是將客戶用到功能性API和SPI分離出來,大大降低了演進(jìn)難度,避免出現(xiàn)將代理與繼承混合時(shí)出現(xiàn)的那種問題。,8.4 合理分解API(1),可以把API分為兩類,一類是供他人調(diào)用來
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 郴州應(yīng)急搶險(xiǎn)管理辦法
- 簽證索賠管理辦法心得
- 贛州戶外燒烤管理辦法
- 鄂州員工寢室管理辦法
- 孕婦學(xué)校培訓(xùn)課件
- 格塞爾培訓(xùn)課件
- 學(xué)習(xí)項(xiàng)目小組培訓(xùn)課件
- 肝癌手術(shù)護(hù)理課件
- 肝癌中醫(yī)課件
- 高新一小學(xué)數(shù)學(xué)試卷
- 2025年工程管理基礎(chǔ)知識(shí)考試試卷及答案
- 2025年湖北省中考英語真題含答案
- 砂石銷售提成管理制度
- 2025年湖南省中考生物試卷及答案
- 聯(lián)想銷售人員管理制度
- 貴州2023年高中學(xué)業(yè)水平合格性考試地理試卷真題(含答案詳解)
- 2025至2030中國(guó)地效飛行器行業(yè)產(chǎn)業(yè)運(yùn)行態(tài)勢(shì)及投資規(guī)劃深度研究報(bào)告
- 2025年四川省眉山市中考化學(xué)試卷及答案
- 乙烯 - 辛烯溶液共聚反應(yīng)機(jī)理及聚合物鏈結(jié)構(gòu)調(diào)控策略探究
- 煤礦隱蔽致災(zāi)因素普查成果礦井自查表
- 2025年重慶市中考語文試卷(含解析)
評(píng)論
0/150
提交評(píng)論