我的筆記本電腦的工作電壓是20V长酗,而我國(guó)的家庭用電是220V,如何讓20V的筆記本電腦能夠在220V的電壓下工作?答案是引入一個(gè)電源適配器(AC Adapter),俗稱(chēng)充電器或變壓器百宇,有了這個(gè)電源適配器,生活用電和筆記本電腦即可兼容
在軟件開(kāi)發(fā)中秘豹,有時(shí)也存在類(lèi)似這種不兼容的情況携御,我們也可以像引入一個(gè)電源適配器一樣引入一個(gè)稱(chēng)之為適配器的角色來(lái)協(xié)調(diào)這些存在不兼容的結(jié)構(gòu),這種設(shè)計(jì)方案即為適配器模式既绕。
1沒(méi)有源碼的算法庫(kù)
Sunny軟件公司在很久以前曾開(kāi)發(fā)了一個(gè)算法庫(kù)啄刹,里面包含了一些常用的算法,例如排序算法和查找算法凄贩,在進(jìn)行各類(lèi)軟件開(kāi)發(fā)時(shí)經(jīng)常需要重用該算法庫(kù)中的算法誓军。在為某學(xué)校開(kāi)發(fā)教務(wù)管理系統(tǒng)時(shí),開(kāi)發(fā)人員發(fā)現(xiàn)需要對(duì)學(xué)生成績(jī)進(jìn)行排序和查找疲扎,該系統(tǒng)的設(shè)計(jì)人員已經(jīng)開(kāi)發(fā)了一個(gè)成績(jī)操作接口ScoreOperation昵时,在該接口中聲明了排序方法sort(int[])和查找方法search(int[], int),為了提高排序和查找的效率椒丧,開(kāi)發(fā)人員決定重用算法庫(kù)中的快速排序算法類(lèi)QuickSort和二分查找算法類(lèi)BinarySearch债查,其中QuickSort的quickSort(int[])方法實(shí)現(xiàn)了快速排序瓜挽,BinarySearch的binarySearch (int[], int)方法實(shí)現(xiàn)了二分查找。
由于某些原因征绸,現(xiàn)在Sunny公司開(kāi)發(fā)人員已經(jīng)找不到該算法庫(kù)的源代碼久橙,無(wú)法直接通過(guò)復(fù)制和粘貼操作來(lái)重用其中的代碼;部分開(kāi)發(fā)人員已經(jīng)針對(duì)ScoreOperation接口編程管怠,如果再要求對(duì)該接口進(jìn)行修改或要求大家直接使用QuickSort類(lèi)和BinarySearch類(lèi)將導(dǎo)致大量代碼需要修改淆衷。
Sunny軟件公司開(kāi)發(fā)人員面對(duì)這個(gè)沒(méi)有源碼的算法庫(kù),遇到一個(gè)幸福而又煩惱的問(wèn)題:如何在既不修改現(xiàn)有接口又不需要任何算法庫(kù)代碼的基礎(chǔ)上能夠?qū)崿F(xiàn)算法庫(kù)的重用渤弛?
通過(guò)分析祝拯,我們不難得知,現(xiàn)在Sunny軟件公司面對(duì)的問(wèn)題有點(diǎn)類(lèi)似本章最開(kāi)始所提到的電壓?jiǎn)栴},成績(jī)操作接口ScoreOperation好比只支持20V電壓的筆記本佳头,而算法庫(kù)好比220V的家庭用電鹰贵,這兩部分都沒(méi)有辦法再進(jìn)行修改,而且它們?cè)臼莾蓚€(gè)完全不相關(guān)的結(jié)構(gòu)
現(xiàn)在我們需要ScoreOperation接口能夠和已有算法庫(kù)一起工作康嘉,讓它們?cè)谕粋€(gè)系統(tǒng)中能夠兼容碉输,最好的實(shí)現(xiàn)方法是增加一個(gè)類(lèi)似電源適配器一樣的適配器角色,通過(guò)適配器來(lái)協(xié)調(diào)這兩個(gè)原本不兼容的結(jié)構(gòu)亭珍。如何在軟件開(kāi)發(fā)中設(shè)計(jì)和實(shí)現(xiàn)適配器是本章我們將要解決的核心問(wèn)題敷钾,下面就讓我們正式開(kāi)始學(xué)習(xí)這種用于解決不兼容結(jié)構(gòu)問(wèn)題的適配器模式。
2 適配器模式概述
與電源適配器相似肄梨,在適配器模式中引入了一個(gè)被稱(chēng)為適配器(Adapter)的包裝類(lèi)阻荒,而它所包裝的對(duì)象稱(chēng)為適配者(Adaptee),即被適配的類(lèi)众羡。適配器的實(shí)現(xiàn)就是把客戶(hù)類(lèi)的請(qǐng)求轉(zhuǎn)化為對(duì)適配者的相應(yīng)接口的調(diào)用侨赡。也就是說(shuō):當(dāng)客戶(hù)類(lèi)調(diào)用適配器的方法時(shí),在適配器類(lèi)的內(nèi)部將調(diào)用適配者類(lèi)的方法纱控,而這個(gè)過(guò)程對(duì)客戶(hù)類(lèi)是透明的辆毡,客戶(hù)類(lèi)并不直接訪(fǎng)問(wèn)適配者類(lèi)。因此甜害,適配器讓那些由于接口不兼容而不能交互的類(lèi)可以一起工作舶掖。
適配器模式可以將一個(gè)類(lèi)的接口和另一個(gè)類(lèi)的接口匹配起來(lái),而無(wú)須修改原來(lái)的適配者接口和抽象目標(biāo)類(lèi)接口尔店。適配器模式定義如下:
適配器模式(Adapter Pattern):將一個(gè)接口轉(zhuǎn)換成客戶(hù)希望的另一個(gè)接口眨攘,使接口不兼容的那些類(lèi)可以一起工作,其別名為包裝器(Wrapper)嚣州。適配器模式既可以作為類(lèi)結(jié)構(gòu)型模式鲫售,也可以作為對(duì)象結(jié)構(gòu)型模式。
【注:在適配器模式定義中所提及的接口是指廣義的接口该肴,它可以表示一個(gè)方法或者方法的集合情竹。】
在適配器模式中匀哄,我們通過(guò)增加一個(gè)新的適配器類(lèi)來(lái)解決接口不兼容的問(wèn)題秦效,使得原本沒(méi)有任何關(guān)系的類(lèi)可以協(xié)同工作。根據(jù)適配器類(lèi)與適配者類(lèi)的關(guān)系不同涎嚼,適配器模式可分為對(duì)象適配器和類(lèi)適配器兩種阱州,在對(duì)象適配器模式中,適配器與適配者之間是關(guān)聯(lián)關(guān)系法梯;在類(lèi)適配器模式中苔货,適配器與適配者之間是繼承(或?qū)崿F(xiàn))關(guān)系。在實(shí)際開(kāi)發(fā)中,對(duì)象適配器的使用頻率更高夜惭,對(duì)象適配器模式結(jié)構(gòu)
在對(duì)象適配器模式結(jié)構(gòu)圖中包含如下幾個(gè)角色:
●Target(目標(biāo)抽象類(lèi)):目標(biāo)抽象類(lèi)定義客戶(hù)所需接口姻灶,可以是一個(gè)抽象類(lèi)或接口,也可以是具體類(lèi)滥嘴。
●Adapter(適配器類(lèi)):適配器可以調(diào)用另一個(gè)接口木蹬,作為一個(gè)轉(zhuǎn)換器,對(duì)Adaptee和Target進(jìn)行適配若皱,適配器類(lèi)是適配器模式的核心镊叁,在對(duì)象適配器中,它通過(guò)繼承Target并關(guān)聯(lián)一個(gè)Adaptee對(duì)象使二者產(chǎn)生聯(lián)系走触。
●Adaptee(適配者類(lèi)):適配者即被適配的角色晦譬,它定義了一個(gè)已經(jīng)存在的接口,這個(gè)接口需要適配互广,適配者類(lèi)一般是一個(gè)具體類(lèi)敛腌,包含了客戶(hù)希望使用的業(yè)務(wù)方法,在某些情況下可能沒(méi)有適配者類(lèi)的源代碼惫皱。
根據(jù)對(duì)象適配器模式結(jié)構(gòu)圖像樊,在對(duì)象適配器中,客戶(hù)端需要調(diào)用request()方法旅敷,而適配者類(lèi)Adaptee沒(méi)有該方法生棍,但是它所提供的specificRequest()方法卻是客戶(hù)端所需要的。為了使客戶(hù)端能夠使用適配者類(lèi)媳谁,需要提供一個(gè)包裝類(lèi)Adapter涂滴,即適配器類(lèi)。這個(gè)包裝類(lèi)包裝了一個(gè)適配者的實(shí)例晴音,從而將客戶(hù)端與適配者銜接起來(lái)柔纵,在適配器的request()方法中調(diào)用適配者的specificRequest()方法。因?yàn)檫m配器類(lèi)與適配者類(lèi)是關(guān)聯(lián)關(guān)系(也可稱(chēng)之為委派關(guān)系)锤躁,所以這種適配器模式稱(chēng)為對(duì)象適配器模式搁料。典型的對(duì)象適配器代碼如下所示:
[java]view plaincopy
classAdapterextendsTarget?{
privateAdaptee?adaptee;//維持一個(gè)對(duì)適配者對(duì)象的引用
publicAdapter(Adaptee?adaptee)?{
this.adaptee=adaptee;
}
publicvoidrequest()?{
adaptee.specificRequest();//轉(zhuǎn)發(fā)調(diào)用
}
}
3 完整解決方案
Sunny軟件公司開(kāi)發(fā)人員決定使用適配器模式來(lái)重用算法庫(kù)中的算法
ScoreOperation接口充當(dāng)抽象目標(biāo),QuickSort和BinarySearch類(lèi)充當(dāng)適配者系羞,OperationAdapter充當(dāng)適配器郭计。完整代碼如下所示:
[java]view plaincopy
//抽象成績(jī)操作類(lèi):目標(biāo)接口
interfaceScoreOperation?{
publicint[]?sort(intarray[]);//成績(jī)排序
publicintsearch(intarray[],intkey);//成績(jī)查找
}
//快速排序類(lèi):適配者
classQuickSort?{
publicint[]?quickSort(intarray[])?{
sort(array,0,array.length-1);
returnarray;
}
publicvoidsort(intarray[],intp,intr)?{
intq=0;
if(p
q=partition(array,p,r);
sort(array,p,q-1);
sort(array,q+1,r);
}
}
publicintpartition(int[]?a,intp,intr)?{
intx=a[r];
intj=p-1;
for(inti=p;i<=r-1;i++)?{
if(a[i]<=x)?{
j++;
swap(a,j,i);
}
}
swap(a,j+1,r);
returnj+1;
}
publicvoidswap(int[]?a,inti,intj)?{
intt?=?a[i];
a[i]?=?a[j];
a[j]?=?t;
}
}
//二分查找類(lèi):適配者
classBinarySearch?{
publicintbinarySearch(intarray[],intkey)?{
intlow?=0;
inthigh?=?array.length?-1;
while(low?<=?high)?{
intmid?=?(low?+?high)?/2;
intmidVal?=?array[mid];
if(midVal?<?key)?{
low?=?mid?+1;
}
elseif(midVal?>?key)?{
high?=?mid?-1;
}
else{
return1;//找到元素返回1
}
}
return-1;//未找到元素返回-1
}
}
//操作適配器:適配器
classOperationAdapterimplementsScoreOperation?{
privateQuickSort?sortObj;//定義適配者QuickSort對(duì)象
privateBinarySearch?searchObj;//定義適配者BinarySearch對(duì)象
publicOperationAdapter()?{
sortObj?=newQuickSort();
searchObj?=newBinarySearch();
}
publicint[]?sort(intarray[])?{
returnsortObj.quickSort(array);//調(diào)用適配者類(lèi)QuickSort的排序方法
}
publicintsearch(intarray[],intkey)?{
returnsearchObj.binarySearch(array,key);//調(diào)用適配者類(lèi)BinarySearch的查找方法
}
}
為了讓系統(tǒng)具備良好的靈活性和可擴(kuò)展性,我們引入了工具類(lèi)XMLUtil和配置文件觉啊,其中,XMLUtil類(lèi)的代碼如下所示:
[java]view plaincopy
importjavax.xml.parsers.*;
importorg.w3c.dom.*;
importorg.xml.sax.SAXException;
importjava.io.*;
classXMLUtil?{
//該方法用于從XML配置文件中提取具體類(lèi)類(lèi)名沈贝,并返回一個(gè)實(shí)例對(duì)象
publicstaticObject?getBean()?{
try{
//創(chuàng)建文檔對(duì)象
DocumentBuilderFactory?dFactory?=?DocumentBuilderFactory.newInstance();
DocumentBuilder?builder?=?dFactory.newDocumentBuilder();
Document?doc;
doc?=?builder.parse(newFile("config.xml"));
//獲取包含類(lèi)名的文本節(jié)點(diǎn)
NodeList?nl?=?doc.getElementsByTagName("className");
Node?classNode=nl.item(0).getFirstChild();
String?cName=classNode.getNodeValue();
//通過(guò)類(lèi)名生成實(shí)例對(duì)象并將其返回
Class?c=Class.forName(cName);
Object?obj=c.newInstance();
returnobj;
}
catch(Exception?e)?{
e.printStackTrace();
returnnull;
}
}
}
配置文件config.xml中存儲(chǔ)了適配器類(lèi)的類(lèi)名杠人,代碼如下所示:
[html]view plaincopy
OperationAdapter
編寫(xiě)如下客戶(hù)端測(cè)試代碼:
[java]view plaincopy
classClient?{
publicstaticvoidmain(String?args[])?{
ScoreOperation?operation;//針對(duì)抽象目標(biāo)接口編程
operation?=?(ScoreOperation)XMLUtil.getBean();//讀取配置文件,反射生成對(duì)象
intscores[]?=?{84,76,50,69,90,91,88,96};//定義成績(jī)數(shù)組
intresult[];
intscore;
System.out.println("成績(jī)排序結(jié)果:");
result?=?operation.sort(scores);
//遍歷輸出成績(jī)
for(inti?:?scores)?{
System.out.print(i?+",");
}
System.out.println();
System.out.println("查找成績(jī)90:");
score?=?operation.search(result,90);
if(score?!=?-1)?{
System.out.println("找到成績(jī)90。");
}
else{
System.out.println("沒(méi)有找到成績(jī)90嗡善。");
}
System.out.println("查找成績(jī)92:");
score?=?operation.search(result,92);
if(score?!=?-1)?{
System.out.println("找到成績(jī)92辑莫。");
}
else{
System.out.println("沒(méi)有找到成績(jī)92。");
}
}
}
編譯并運(yùn)行程序罩引,輸出結(jié)果如下:
成績(jī)排序結(jié)果:
50,69,76,84,88,90,91,96,
查找成績(jī)90:
找到成績(jī)90各吨。
查找成績(jī)92:
沒(méi)有找到成績(jī)92。
在本實(shí)例中使用了對(duì)象適配器模式袁铐,同時(shí)引入了配置文件揭蜒,將適配器類(lèi)的類(lèi)名存儲(chǔ)在配置文件中。如果需要使用其他排序算法類(lèi)和查找算法類(lèi)剔桨,可以增加一個(gè)新的適配器類(lèi)屉更,使用新的適配器來(lái)適配新的算法,原有代碼無(wú)須修改洒缀。通過(guò)引入配置文件和反射機(jī)制瑰谜,可以在不修改客戶(hù)端代碼的情況下使用新的適配器,無(wú)須修改源代碼树绩,符合“開(kāi)閉原則”萨脑。
4類(lèi)適配器
除了對(duì)象適配器模式之外,適配器模式還有一種形式饺饭,那就是類(lèi)適配器模式渤早,類(lèi)適配器模式和對(duì)象適配器模式最大的區(qū)別在于適配器和適配者之間的關(guān)系不同,對(duì)象適配器模式中適配器和適配者之間是關(guān)聯(lián)關(guān)系砰奕,而類(lèi)適配器模式中適配器和適配者是繼承關(guān)系
根據(jù)類(lèi)適配器模式結(jié)構(gòu)圖蛛芥,適配器類(lèi)實(shí)現(xiàn)了抽象目標(biāo)類(lèi)接口Target,并繼承了適配者類(lèi)军援,在適配器類(lèi)的request()方法中調(diào)用所繼承的適配者類(lèi)的specificRequest()方法仅淑,實(shí)現(xiàn)了適配。
典型的類(lèi)適配器代碼如下所示:
[java]view plaincopy
classAdapterextendsAdapteeimplementsTarget?{
publicvoidrequest()?{
specificRequest();
}
}
由于Java胸哥、C#等語(yǔ)言不支持多重類(lèi)繼承涯竟,因此類(lèi)適配器的使用受到很多限制,例如如果目標(biāo)抽象類(lèi)Target不是接口空厌,而是一個(gè)類(lèi)庐船,就無(wú)法使用類(lèi)適配器;此外嘲更,如果適配者Adapter為最終(Final)類(lèi)筐钟,也無(wú)法使用類(lèi)適配器。在Java等面向?qū)ο缶幊陶Z(yǔ)言中赋朦,大部分情況下我們使用的是對(duì)象適配器篓冲,類(lèi)適配器較少使用李破。
6 缺省適配器
缺省適配器模式是適配器模式的一種變體,其應(yīng)用也較為廣泛壹将。缺省適配器模式的定義如下:
缺省適配器模式(Default Adapter Pattern):當(dāng)不需要實(shí)現(xiàn)一個(gè)接口所提供的所有方法時(shí)嗤攻,可先設(shè)計(jì)一個(gè)抽象類(lèi)實(shí)現(xiàn)該接口,并為接口中每個(gè)方法提供一個(gè)默認(rèn)實(shí)現(xiàn)(空方法)诽俯,那么該抽象類(lèi)的子類(lèi)可以選擇性地覆蓋父類(lèi)的某些方法來(lái)實(shí)現(xiàn)需求妇菱,它適用于不想使用一個(gè)接口中的所有方法的情況,又稱(chēng)為單接口適配器模式暴区。
在缺省適配器模式中闯团,包含如下三個(gè)角色:
●ServiceInterface(適配者接口):它是一個(gè)接口,通常在該接口中聲明了大量的方法颜启。
●AbstractServiceClass(缺省適配器類(lèi)):它是缺省適配器模式的核心類(lèi)偷俭,使用空方法的形式實(shí)現(xiàn)了在ServiceInterface接口中聲明的方法。通常將它定義為抽象類(lèi)缰盏,因?yàn)閷?duì)它進(jìn)行實(shí)例化沒(méi)有任何意義涌萤。
●ConcreteServiceClass(具體業(yè)務(wù)類(lèi)):它是缺省適配器類(lèi)的子類(lèi),在沒(méi)有引入適配器之前口猜,它需要實(shí)現(xiàn)適配者接口负溪,因此需要實(shí)現(xiàn)在適配者接口中定義的所有方法,而對(duì)于一些無(wú)須使用的方法也不得不提供空實(shí)現(xiàn)济炎。在有了缺省適配器之后川抡,可以直接繼承該適配器類(lèi),根據(jù)需要有選擇性地覆蓋在適配器類(lèi)中定義的方法须尚。
在JDK類(lèi)庫(kù)的事件處理包Java.awt.event中廣泛使用了缺省適配器模式崖堤,如WindowAdapter、KeyAdapter耐床、MouseAdapter等密幔。下面我們以處理窗口事件為例來(lái)進(jìn)行說(shuō)明:在Java語(yǔ)言中,一般我們可以使用兩種方式來(lái)實(shí)現(xiàn)窗口事件處理類(lèi)撩轰,一種是通過(guò)實(shí)現(xiàn)WindowListener接口胯甩,另一種是通過(guò)繼承WindowAdapter適配器類(lèi)。如果是使用第一種方式堪嫂,直接實(shí)現(xiàn)WindowListener接口偎箫,事件處理類(lèi)需要實(shí)現(xiàn)在該接口中定義的七個(gè)方法,而對(duì)于大部分需求可能只需要實(shí)現(xiàn)一兩個(gè)方法皆串,其他方法都無(wú)須實(shí)現(xiàn)淹办,但由于語(yǔ)言特性我們不得不為其他方法也提供一個(gè)簡(jiǎn)單的實(shí)現(xiàn)(通常是空實(shí)現(xiàn)),這給使用帶來(lái)了麻煩恶复。而使用缺省適配器模式就可以很好地解決這一問(wèn)題怜森,在JDK中提供了一個(gè)適配器類(lèi)WindowAdapter來(lái)實(shí)現(xiàn)WindowListener接口齐遵,該適配器類(lèi)為接口中的每一個(gè)方法都提供了一個(gè)空實(shí)現(xiàn),此時(shí)事件處理類(lèi)可以繼承WindowAdapter類(lèi)塔插,而無(wú)須再為接口中的每個(gè)方法都提供實(shí)現(xiàn)
7 適配器模式總結(jié)
適配器模式將現(xiàn)有接口轉(zhuǎn)化為客戶(hù)類(lèi)所期望的接口,實(shí)現(xiàn)了對(duì)現(xiàn)有類(lèi)的復(fù)用拓哟,它是一種使用頻率非常高的設(shè)計(jì)模式想许,在軟件開(kāi)發(fā)中得以廣泛應(yīng)用,在spring等開(kāi)源框架断序、驅(qū)動(dòng)程序設(shè)計(jì)(如JDBC中的數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序)中也使用了適配器模式流纹。
1.主要優(yōu)點(diǎn)
無(wú)論是對(duì)象適配器模式還是類(lèi)適配器模式都具有如下優(yōu)點(diǎn):
(1)將目標(biāo)類(lèi)和適配者類(lèi)解耦,通過(guò)引入一個(gè)適配器類(lèi)來(lái)重用現(xiàn)有的適配者類(lèi)违诗,無(wú)須修改原有結(jié)構(gòu)漱凝。
(2)增加了類(lèi)的透明性和復(fù)用性,將具體的業(yè)務(wù)實(shí)現(xiàn)過(guò)程封裝在適配者類(lèi)中诸迟,對(duì)于客戶(hù)端類(lèi)而言是透明的,而且提高了適配者的復(fù)用性,同一個(gè)適配者類(lèi)可以在多個(gè)不同的系統(tǒng)中復(fù)用宿百。
(3)靈活性和擴(kuò)展性都非常好洲拇,通過(guò)使用配置文件,可以很方便地更換適配器绅项,也可以在不修改原有代碼的基礎(chǔ)上增加新的適配器類(lèi)紊册,完全符合“開(kāi)閉原則”。
具體來(lái)說(shuō)快耿,類(lèi)適配器模式還有如下優(yōu)點(diǎn):
由于適配器類(lèi)是適配者類(lèi)的子類(lèi)囊陡,因此可以在適配器類(lèi)中置換一些適配者的方法,使得適配器的靈活性更強(qiáng)掀亥。
對(duì)象適配器模式還有如下優(yōu)點(diǎn):
(1)一個(gè)對(duì)象適配器可以把多個(gè)不同的適配者適配到同一個(gè)目標(biāo)撞反;
(2)可以適配一個(gè)適配者的子類(lèi),由于適配器和適配者之間是關(guān)聯(lián)關(guān)系铺浇,根據(jù)“里氏代換原則”痢畜,適配者的子類(lèi)也可通過(guò)該適配器進(jìn)行適配。
2.主要缺點(diǎn)
類(lèi)適配器模式的缺點(diǎn)如下:
(1)對(duì)于Java鳍侣、C#等不支持多重類(lèi)繼承的語(yǔ)言丁稀,一次最多只能適配一個(gè)適配者類(lèi),不能同時(shí)適配多個(gè)適配者倚聚;
(2)適配者類(lèi)不能為最終類(lèi)线衫,如在Java中不能為final類(lèi),C#中不能為sealed類(lèi)惑折;
(3)在Java授账、C#等語(yǔ)言中枯跑,類(lèi)適配器模式中的目標(biāo)抽象類(lèi)只能為接口,不能為類(lèi)白热,其使用有一定的局限性敛助。
對(duì)象適配器模式的缺點(diǎn)如下:
與類(lèi)適配器模式相比,要在適配器中置換適配者類(lèi)的某些方法比較麻煩屋确。如果一定要置換掉適配者類(lèi)的一個(gè)或多個(gè)方法纳击,可以先做一個(gè)適配者類(lèi)的子類(lèi),將適配者類(lèi)的方法置換掉攻臀,然后再把適配者類(lèi)的子類(lèi)當(dāng)做真正的適配者進(jìn)行適配焕数,實(shí)現(xiàn)過(guò)程較為復(fù)雜。
3.適用場(chǎng)景
在以下情況下可以考慮使用適配器模式:
(1)系統(tǒng)需要使用一些現(xiàn)有的類(lèi)刨啸,而這些類(lèi)的接口(如方法名)不符合系統(tǒng)的需要堡赔,甚至沒(méi)有這些類(lèi)的源代碼。
(2)想創(chuàng)建一個(gè)可以重復(fù)使用的類(lèi)设联,用于與一些彼此之間沒(méi)有太大關(guān)聯(lián)的一些類(lèi)善已,包括一些可能在將來(lái)引進(jìn)的類(lèi)一起工作。