java適配器模式
首先,先來(lái)先講講適配器。適配就是由“源”到“目標(biāo)”的適配,而當(dāng)中鏈接兩者的關(guān)系就是適配器。它負(fù)責(zé)把“源”過(guò)度到“目標(biāo)”。舉個(gè)簡(jiǎn)單的例子,比如有一個(gè)“源”是一個(gè)對(duì)象人,他擁有2種技能分別是說(shuō)日語(yǔ)和說(shuō)英語(yǔ),而某個(gè)崗位(目標(biāo))需要你同時(shí)回說(shuō)日語(yǔ)、英語(yǔ)、和法語(yǔ),好了,現(xiàn)在我們的任務(wù)就是要將人這個(gè)“源”適配的這個(gè)崗位中,如何適配呢?顯而易見(jiàn)地我們需要為人添加一個(gè)說(shuō)法語(yǔ)的方法,這樣才能滿足目標(biāo)的需要。
接著討論如何加說(shuō)法語(yǔ)這個(gè)方法,也許你會(huì)說(shuō),為什么不直接在“源”中直接添加方法,我的理解是,適配是為了實(shí)現(xiàn)某種目的而為一個(gè)源類暫時(shí)性的加上某種方法,所以不能破壞原類的結(jié)構(gòu)。同時(shí)不這么做也符合Java的高內(nèi)聚,低耦合的原理。既然不能直接加,接著我們就來(lái)說(shuō)該怎么來(lái)實(shí)現(xiàn)為人這個(gè)“源”添加一個(gè)方法,而又不破壞“源”的本身結(jié)構(gòu)。
適配器模式有2種,第一種是“面向類的適配器模式”,第二種是“面向?qū)ο蟮倪m配器模式”。
先說(shuō)“面向類的適配器模式”。顧名思義,這類適配器模式就是主要用于,單一的為某個(gè)類而實(shí)現(xiàn)適配的這樣一種模式,為什么說(shuō)只為某個(gè)類去實(shí)現(xiàn),一會(huì)提到,我們先展示這種類適配模式的代碼實(shí)現(xiàn)。
源的代碼如下:
[c-sharp] view plain copypublic class Person {
private String name;
private String sex;
private int age;
public void speakJapanese(){
System.out.println(“I can speak Japanese!”);
}
public void speakEnglish(){
System.out.println(“I can speak English!”);
}
。。。//以下省略成員變量的get和set方法
}
目標(biāo)接口的代碼如下:
[c-sharp] view plain copypublic interface Job {
public abstract void speakJapanese();
public abstract void speakEnglish();
public abstract void speakFrench();
}
適配器的代碼如下:
[c-sharp] view plain copypublic class Adapter extends Person implements Job{
public void speakFrench() {
}
}
好了,代碼看完然后要做一些說(shuō)明了,之前遺留的一個(gè)問(wèn)題,為什么稱其為類適配模式呢?很顯然的,Adapter類繼承了Person類,而在Java這種單繼承的語(yǔ)言中也就意味著,他不可能再去繼承其他的類了,這樣也就是這個(gè)適配器只為Person這一個(gè)類服務(wù)。所以稱其為類適配模式。
說(shuō)完類的適配模式,我們要開(kāi)始說(shuō)第2種對(duì)象的適配器模式了。對(duì)象適配器模式是把“源”作為一個(gè)對(duì)象聚合到適配器類中。同樣的話不多說(shuō),貼上代碼:
源的代碼以及目標(biāo)代碼同上,再次不再贅述。
僅貼出適配器代碼:
[c-sharp] view plain copypublic class Adapter implements Job {
Person person;
public Adapter(Person person) {
this.person = person;
}
public void speakEnglish() {
person.speakEnglish();
}
public void speakJapanese() {
person.speakJapanese();
}
//new add
public void speakFrench() {
}
}
對(duì)象的適配器模式,把“源”作為一個(gè)構(gòu)造參數(shù)傳入適配器,然后執(zhí)行接口所要求的方法。這種適配模式可以為多個(gè)源進(jìn)行適配。彌補(bǔ)了類適配模式的不足。
現(xiàn)在來(lái)對(duì)2種適配模式做個(gè)分析:
1.類的適配模式用于單一源的適配,由于它的源的單一話,代碼實(shí)現(xiàn)不用寫(xiě)選擇邏輯,很清晰;而對(duì)象的適配模式則可用于多源的適配,彌補(bǔ)了類適配模式的不足,使得原本用類適配模式需要寫(xiě)很多適配器的情況不復(fù)存在,弱點(diǎn)是,由于源的數(shù)目可以較多,所以具體的實(shí)現(xiàn)條件選擇分支比較多,不太清晰。
2.適配器模式主要用于幾種情況:(1)系統(tǒng)需要使用現(xiàn)有的類,但現(xiàn)有的類不完全符合需要。(2)講彼此沒(méi)有太大關(guān)聯(lián)的類引進(jìn)來(lái)一起完成某項(xiàng)工作(指對(duì)象適配)。
最后,再來(lái)順帶談?wù)勀J(rèn)適配器模式:這種模式的核心歸結(jié)如下:當(dāng)你想實(shí)現(xiàn)一個(gè)接口但又不想實(shí)現(xiàn)所有接口方法,只想去實(shí)現(xiàn)一部分方法時(shí),就用中默認(rèn)的適配器模式,他的方法是在接口和具體實(shí)現(xiàn)類中添加一個(gè)抽象類,而用抽象類去空實(shí)現(xiàn)目標(biāo)接口的所有方法。而具體的實(shí)現(xiàn)類只需要覆蓋其需要完成的方法即可。代碼如下:
接口類:
[c-sharp] view plain copypublic interface Job {
public abstract void speakJapanese();
public abstract void speakEnglish();
public abstract void speakFrench();
public abstract void speakChinese();
}
抽象類:
[c-sharp] view plain copypublic abstract class JobDefault implements Job{
public void speakChinese() {
}
public void speakEnglish() {
}
public void speakFrench() {
}
public void speakJapanese() {
}
}
實(shí)現(xiàn)類:
[c-sharp] view plain copypublic class JobImpl extends JobDefault{
public void speakChinese(){
System.out.println(“I can speak Chinese!”);
}
}
java適配器模式實(shí)例
將一個(gè)類的接口轉(zhuǎn)換成客戶想要的另一個(gè)接口,適配器模式使得原本由于接口不兼容而不能一起工作的那些類可以一起工作
適配器一共包括3種角色
1、目標(biāo):目標(biāo)是一個(gè)接口,該接口是客戶想使用的接口
2、被適配者:被適配者是一個(gè)已存在的接口或抽象類,這個(gè)接口或抽象類需要適配
3、適配器:適配器是一個(gè)類,該類實(shí)現(xiàn)了目標(biāo)接口并包含有被適配者的引用,即適配者的指著是對(duì)被適配者接口與目標(biāo)進(jìn)行適配
[java] view plain copypackage org.zhy.adapter;
/**
* 目標(biāo)
* @author zhengyi
*
*/
public interface ThreeElectricOutlet {
//用來(lái)刻畫(huà)三相插座
public abstract void connectElectricCurrent();
}
[java] view plain copypackage org.zhy.adapter;
/**
* 適配器
* @author zhengyi
*
*/
public class TreeElecricAdapter implements ThreeElectricOutlet {
TwoElectricOutlet outlet;
public TreeElecricAdapter(TwoElectricOutlet teo) {
this.outlet=teo;
}
@Override
public void connectElectricCurrent() {
outlet.connectElectricCurrent();
}
}
[java] view plain copypackage org.zhy.adapter;
/**
* 被適配者
* @author zhengyi
*
*/
public interface TwoElectricOutlet {
//刻畫(huà)兩相插座
public abstract void connectElectricCurrent();
}
[java] view plain copypackage org.zhy.adapter;
public class Appliction {
public static void main(String[] args) {
ThreeElectricOutlet outlet; //目標(biāo)接口三相插座
Wash wash=new Wash();
outlet=wash;
System.out.println(“使用三相插座接通電流”);
outlet.connectElectricCurrent();
Tv tv=new Tv();
TreeElecricAdapter adapter=new TreeElecricAdapter(tv);
outlet= adapter;
System.out.println(“使用三相插座接通電流”);
outlet.connectElectricCurrent();
}
}
[java] view plain copypackage org.zhy.adapter;
/**
* 洗衣機(jī)
* @author zhengyi
*
*/
public class Wash implements ThreeElectricOutlet {
private String name;
public Wash() {
name=“洗衣機(jī)”;
}
public Wash(String name){
this.name=name;
}
@Override
public void connectElectricCurrent() {
turnOn();
}
private void turnOn(){
System.out.println(name+“開(kāi)始洗衣服”);
}
}
[java] view plain copypackage org.zhy.adapter;
/**
* 電視
* @author zhengyi
*
*/
public class Tv implements TwoElectricOutlet {
private String name;
public Tv() {
name=“長(zhǎng)江電視機(jī)”;
}
public Tv(String s){
this.name=s;
}
@Override
public void connectElectricCurrent() {
turnOn();
}
private void turnOn(){
System.out.println(name+“開(kāi)始播放節(jié)目”);
}
}
適配器的適配程度
1、完全適配
如果目標(biāo)接口中的方法數(shù)目與被適配者接口的方法數(shù)目相等那么適配器可將被適配者接口與目標(biāo)接口進(jìn)行完全適配
2、不完全適配
如果目標(biāo)接口中的方法數(shù)目少于被適配者接口的方法數(shù)目那么適配器只能將被適配者接口與目標(biāo)接口進(jìn)行適配
3、剩余適配
如果目標(biāo)接口中的方法數(shù)目大于被適配者接口的方法數(shù)目。那么適配器可將被適配者接口與目標(biāo)接口進(jìn)行完全適配,但必須將目標(biāo)多余的方法給出用戶允許默認(rèn)實(shí)現(xiàn)
適配器模式的優(yōu)點(diǎn)
1、目標(biāo)和適配者是完全解耦的關(guān)系
2、適配器模式滿足“開(kāi)-閉原則”當(dāng)添加一個(gè)實(shí)現(xiàn)Adaptee接口的新類時(shí),不必修改Adaptee,而Adaptee就能對(duì)這個(gè)新類的實(shí)例進(jìn)行適配
評(píng)論