實例講解JAVA 適配器模式
在講述這個模式之前,我們先看一個案例:中國球員去NBA打籃球
中國球員去NBA打籃球,可是他不懂英語,所以聽不懂教練安排的戰(zhàn)術(shù),所以現(xiàn)在有三種解決方式
1、球員學(xué)會英語。2、教練學(xué)會中文。3、請個翻譯。
1和2是長久之計,但不能解決迫在眉睫的問題。請個翻譯是短暫的更好的選擇。
放在軟件設(shè)計層面上,這就叫做適配器模式。http://www.dbjr.com.cn/article/189484.htm
將一個類的接口轉(zhuǎn)換成客戶希望的另外一個接口。適配器模式使得原本由于接口不兼容而不能一起工作的那些類可以一起工作。
在軟件開發(fā)中,也就是系統(tǒng)的數(shù)據(jù)和行為都正確,但接口不符時,我們應(yīng)該考慮用適配器,目的是使控制范圍之外的一個原有對象與某個接口匹配,適配器模式主要應(yīng)用于希望復(fù)用一些現(xiàn)存的類,但是接口又與復(fù)用環(huán)境要求不一致的情況。
在 GoF 的設(shè)汁模式中,對適配器模式講了兩種類型,類適配器模式和對象適配器模式,由于類適配器模式通過多重繼承對一個接口與另一個接口進行匹配,而JAVA語言不支持多重繼承,也就是一個類只有一個父類,所以我們這里主要講的是對象適配器。
Target(這是客戶所期待的接口。目標可以是具體的或抽象的類,也可以是接口)代碼如下:
public class Target {
public void request() {
System.out.println("普通請求");
}
}
Adaptee(需要適配的類)代碼如下:
public class Adaptee {
public void specialRequest(){
System.out.println("特殊請求");
}
}
Adapter(通過在內(nèi)部包裝一個Adaptee對象,把原接口轉(zhuǎn)換成目標接口)代碼如下:
public class Adapter extends Target{
private Adaptee adaptee = new Adaptee();//建立一個私有的Adaptee對象
@Override
public void request() {
//這樣就可以把表面上調(diào)用request()方法變成實際調(diào)用的specialRequest()
adaptee.specialRequest();
}
}
測試方法
public class Test {
public static void main(String[] args) {
//對main方法來說,調(diào)用的就是Target的request()
Target target = new Target();
target.request();
}
}
看起來是不是很簡單,是不是跟一句俗語很像“掛羊頭賣狗肉”。
何時使用適配器模式?
在想使用一個已經(jīng)存在的類,但如果它的接口,也就是它的方法和你的要求不相同時,就應(yīng)該考慮用適配器模式。兩個類所做的事情相同或相似,但是具有不同的接口時要使用它。而且由于類都共亨同一個接口,代碼可以統(tǒng)一調(diào)用同一接口就行了,這樣應(yīng)該可以更簡單、更直接、更緊湊。
其實用適配器模式也是無奈之舉,很有點‘亡羊補牢'的感覺,沒辦法呀,是軟件就有維護的一天,維護就有可能會因不同的開發(fā)人員、不同的產(chǎn)品、不同的廠家而造成功能類似而接口不同的情況,此時就是適配器模式大展拳腳的時候了。
現(xiàn)在把教練給球員們分配任務(wù)的例子用適配器模式實現(xiàn)
球員類
public abstract class Player {
protected String name;
public Player(String name) {
this.name = name;
}
//進攻和防守方法
public abstract void attack();
public abstract void defense();
}
后衛(wèi)、中鋒、前鋒類
//前鋒
public class Forwards extends Player {
public Forwards(String name) {
super(name);
}
@Override
public void attack() {
System.out.println("前鋒:"+name+"進攻");
}
@Override
public void defense() {
// TODO Auto-generated method stub
System.out.println("前鋒:"+name+"防守");
}
}
//中鋒
public class Center extends Player {
public Center(String name) {
super(name);
}
@Override
public void attack() {
System.out.println("中鋒:"+name+"進攻");
}
@Override
public void defense() {
// TODO Auto-generated method stub
System.out.println("中鋒:"+name+"防守");
}
}
//后衛(wèi)
public class Guards extends Player {
public Guards(String name) {
super(name);
}
@Override
public void attack() {
System.out.println("后衛(wèi):"+name+"進攻");
}
@Override
public void defense() {
// TODO Auto-generated method stub
System.out.println("后衛(wèi):"+name+"防守");
}
}
測試方法
public class Test {
public static void main(String[] args) {
Player peter = new Forwards("peter");
peter.attack();
Player mike = new Guards("mike");
mike.attack();
Player zhangsan = new Center("張三");
zhangsan.attack();
zhangsan.defense();
}
}
輸出結(jié)果:
前鋒:peter進攻
后衛(wèi):mike進攻
中鋒:張三進攻
中鋒:張三防守
球員“張三”不會說英語,需要翻譯,用適配器模式完善代碼
//外籍中鋒
public class ForeignCenter {
private String name;
//外籍中鋒只懂得中文“進攻”
public void jingong() {
System.out.println("中鋒:"+name+"進攻");
}
//外籍中鋒只懂得中文“防守”
public void fangshou() {
System.out.println("中鋒:"+name+"防守");
}
//省略getter、setter方法
}
//翻譯者
public class Translator extends Player {
//聲明并實例化一個內(nèi)部“外籍中鋒”對象,表面翻譯者與外籍球員有關(guān)聯(lián)
private ForeignCenter wjzf = new ForeignCenter();
public Translator(String name) {
super(name);
wjzf.setName(name);
}
@Override
public void attack() {
//翻譯者將attack翻譯為jingong 告訴外籍中鋒
wjzf.jingong();
}
@Override
public void defense() {
//翻譯者將defense翻譯為fangshou 告訴外籍中鋒
wjzf.fangshou();
}
}
main方法修改代碼如下:
//翻譯者
public class Translator extends Player {
//聲明并實例化一個內(nèi)部“外籍中鋒”對象,表面翻譯者與外籍球員有關(guān)聯(lián)
private ForeignCenter wjzf = new ForeignCenter();
public Translator(String name) {
super(name);
wjzf.setName(name);
}
@Override
public void attack() {
//翻譯者將attack翻譯為jingong 告訴外籍中鋒
wjzf.jingong();
}
@Override
public void defense() {
//翻譯者將defense翻譯為fangshou 告訴外籍中鋒
wjzf.fangshou();
}
}
現(xiàn)在就算是張三不懂英文,教練不懂中文,但因為有了翻譯者,團隊溝通合作成為了可能。
如果能事先預(yù)防接口不同的問題,不匹配問題就不會發(fā)生:在有小的接口不統(tǒng)一問題發(fā)生時,及時重構(gòu),問題不至于擴大:只有碰到無法改變原有設(shè)計和代碼的情況時,才考慮適配。
事后控制不如事中控制,事中控制不如事前控制。
以上就是實例講解JAVA 適配器模式的詳細內(nèi)容,更多關(guān)于JAVA 適配器模式的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java實戰(zhàn)花店商城系統(tǒng)的實現(xiàn)流程
只學(xué)書上的理論是遠遠不夠的,只有在實戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+Springboot+Maven+mybatis+Vue+Mysql實現(xiàn)一個花店商城系統(tǒng),大家可以在過程中查缺補漏,提升水平2022-01-01
基于SpringBoot bootstrap.yml配置未生效的解決
這篇文章主要介紹了基于SpringBoot bootstrap.yml配置未生效的解決方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10
springboot+mybatis-plus基于攔截器實現(xiàn)分表的示例代碼
本文主要介紹了springboot+mybatis-plus基于攔截器實現(xiàn)分表,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-11-11

