这里记录下适配器模式。
适配器模式:将一个类的接口转换成客户希望的另外一个类的接口
定义有点绕,笔者只看定义也理解不了。
今次更换一下说明方式。
现有NBA运动员接口如下:
package com.gcc.adapterModel;
public interface Player {
void attack();
void defense();
}
有NBA前锋类和后卫类如下:
package com.gcc.adapterModel;
public class Forwards implements Player{
String name;
public Forwards() {
super();
}
public Forwards(String name) {
super();
this.name = name;
}
@Override
public void attack() {
System.out.println(name+"前锋进攻");
}
@Override
public void defense() {
System.out.println(name+"前锋防守");
}
}
package com.gcc.adapterModel;
public class Guards implements Player{
String name;
public Guards() {
super();
}
public Guards(String name) {
super();
this.name = name;
}
@Override
public void attack() {
System.out.println(name+"后卫进攻");
}
@Override
public void defense() {
System.out.println(name+"后卫防守");
}
}
这几个类可以理解为A子系统原先就有的,而B子系统原先就存在的中国中锋类如下:
package com.gcc.adapterModel;
public class ChineseCenter implements ChinesePlayer {
String name;
public ChineseCenter() {
super();
}
public ChineseCenter(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//姚明听到翻译的话,执行对应行为
@Override
public void chineseAttack(){
System.out.println(name+"中国中锋进攻");
}
@Override
public void chineseDefense(){
System.out.println(name+"中国中锋防守");
}
}
中国运动员接口如下:
package com.gcc.adapterModel;
public interface ChinesePlayer {
void chineseAttack();
void chineseDefense();
}
这时存在一个调用者(教练)只会使用attack方法,也知道中国中锋有attack方法相符的行为(方法),但他不知道这个行文的名字叫chineseAttack,要符合开闭原则,也就是说在不修改源码的情况下要执行类似attack的方法,即chinsesAttack方法,需要怎么补充?
这时添加适配器类即可,既然中国中锋听不懂英文attack,那么添加一个能听懂的翻译(适配器类)即可,然后让翻译告诉中国中锋去执行名字不同但行为类似的方法。
如下:
package com.gcc.adapterModel;
public class Translate implements Player {
ChineseCenter chineseCenter;
public Translate() {
super();
}
//适配器(翻译)和姚明搭话
public Translate(String name) {
chineseCenter=new ChineseCenter();
chineseCenter.setName(name);
}
//适配器(翻译)告诉姚明attack就是chineseAttack,然后姚明就去执行
@Override
public void attack() {
chineseCenter.chineseAttack();
}
@Override
public void defense() {
chineseCenter.chineseDefense();
}
}
测试类如下,将原本通过ChinesePlayer接口来调用chineseAttack方法的行为改为通过适配器来调用:
package com.gcc.adapterModel;
/**
* 1:适配器模式:姚明在NBA打球,在不能让姚明立刻学会英语也不能立刻让教练和队友说中文的情况下,
* 为了更好的工作,需要翻译(适配器)来帮助姚明。
* 2:适配器使用时机,一般为后期维护时候,而不是设计开发时候。例如,姚明是去nba才发现需要英语,才去找翻译的(适配器),
* 假如早已经计划会去nba则应当已经会英语,就不再需要翻译(适配器)
*/
public class TestAdapter {
public static void main(String[] args) {
new Forwards("巴蒂尔").defense();
new Guards("麦迪").attack();
//new ChineseCenter("姚明").chineseAttack();//调用者并不知道什么chineseAttack方法所以不能调用,可以理解为教练不会说中文
new Translate("姚明").attack();//翻译告诉姚明attack是什么意思,姚明听懂后执行对应的行为
new Translate("姚明").defense();
}
}
/*
* 使用适配器具体说明:
* 姚明必须使用所有队友都能听懂但他听不懂的attack()
* 姚明只能听懂chineseAttack()
* 所以请了翻译,翻译听懂attack()是什么意思,传达给姚明,姚明理解明白后执行chineseAttack,而chineseAttack和attack其实是类似的
*/
这里在此点明,适配器模式是一种补救措施,在功能越来越复杂以后,最先设计的接口无法满足,而又存在两个类所做的事情相同或相似的情况下才适合使用。
最后补充个UML图: