适配器模式(Adapter Pattern):是作为两个不兼容的接口之间的桥梁。将某个类的接口转换为接口客户所需的类型。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。
换句话说,适配器模式解决的问题是,使得原本由于接口不兼容而不能一起工作、不能统一管理的那些类阔以再一起工作、可以进行统一的管理。
例如需求:厨师的工作是cook(),程序员的工作是program(),司机的工作是drive(),老师的工作是teach(),不同的职业,其具体的工作内容是不同的。现在程序要将这些(例如有30个不同职业)不同职业的工作内容全部输出。
解决一:传统方式,逐个访问每个职业对象对应的工作方法。无法循环遍历,无法统一管理。
解决二:使用适配器模式,将这些不兼容的具体工作转换为一个统一的工作,实现循环遍历。
代码示例:
1.不使用适配器编程:
//厨师接口定义
public interface ICooker {
String cook();
}
//程序员接口定义
public interface IProgrammer {
String pragramer();
}
//厨师接口实现
public class ScCooker implements ICooker {
@Override
public String cook() {
return "厨师做菜";
}
}
//程序员接口实现
public class TecentProgrammer implements IProgrammer {
@Override
public String pragramer() {
return "编写程序";
}
}
//主方法测试
public class Test {
public static void main(String[] args) {
ICooker cooker = new ScCooker();
IProgrammer programer = new TecentProgrammer();
System.out.println(cooker.cook());
System.out.println(programer.pragramer());
}
}
/**************************************执行结果*****************************************/
厨师做菜
编写程序
问题:若职业多了,需要创建执行很多次重复的输出语句,不能循环遍历,即不能统一管理。
2.使用一个适配器进行编程
//厨师接口定义
public interface ICooker {
String cook();
}
//程序员接口定义
public interface IProgrammer {
String pragramer();
}
//厨师接口实现
public class ScCooker implements ICooker {
@Override
public String cook() {
return "厨师做菜";
}
}
//程序员接口实现
public class TecentProgrammer implements IProgrammer {
@Override
public String pragramer() {
return "编写程序";
}
}
//适配器接口定义
public interface IWorkAdapter {
String work(Object worker);
}
//适配器类=>实现适配器接口
public class WorkerAdapter implements IWorkAdapter {
@Override
public String work(Object worker) {
String workContent = "";
// 若传来的对象是厨师,则调用cook()方法
if (worker instanceof ICooker) {
workContent = ((ICooker) worker).cook();
} else if (worker instanceof IProgrammer) {
workContent = ((IProgrammer) worker).pragramer();
}
return workContent;
}
}
//主方法测试
public class Test {
public static void main(String[] args) {
ICooker cooker = new ScCooker();
IProgrammer programer = new TecentProgrammer();
Object[] workers = { cooker, programer };
//创建适配器对象
IWorkAdapter adapter = new WorkerAdapter();
// 实现遍历,让每一个职位对象在适配器中逐个进行匹配
for (Object worker : workers) {
String workContent = adapter.work(workers);
System.out.println(workContent);
}
}
}
3.使用多个适配器编程
//厨师接口定义
public interface ICooker {
String cook();
}
//程序员接口定义
public interface IProgrammer {
String pragramer();
}
//厨师接口实现
public class ScCooker implements ICooker {
@Override
public String cook() {
return "厨师做菜";
}
}
//程序员接口实现
public class TecentProgrammer implements IProgrammer {
@Override
public String pragramer() {
return "编写程序";
}
}
//适配器接口定义
public interface IWorkAdapter {
String work(Object worker);
boolean supports(Object worker);
}
//Cooker适配器
public class CookerAdapter implements IWorkAdapter {
@Override
public String work(Object worker) {
return ((ICooker) worker).cook();
}
@Override
public boolean supports(Object worker) {
return (worker instanceof ICooker);
}
}
//Programmer适配器
public class ProgrammerAdapter implements IWorkAdapter {
@Override
public String work(Object worker) {
return ((IProgrammer) worker).pragramer();
}
@Override
public boolean supports(Object worker) {
return (worker instanceof IProgrammer);
}
}
//主方法测试
public class Test {
public static void main(String[] args) {
ICooker cooker = new ScCooker();
IProgrammer programer = new TecentProgrammer();
Object[] workers = { cooker, programer };
// 实现遍历,让每一个职位对象在适配器中逐个进行匹配
for (Object worker : workers) {
// 获取对应的适配器
IWorkAdapter adapter = getAdapter(worker);
System.out.println(adapter.work(worker));
}
}
/**
* 根据worker获取相应的适配器对象
*
* @param worker
* @return
*/
private static IWorkAdapter getAdapter(Object worker) {
// 获取所有的适配器
List<IWorkAdapter> list = getAllAdapters();
// 遍历适配器,判断worker属于哪一个适配器
for (IWorkAdapter adapter : list) {
// 调用适配器中的support()方法
if (adapter.supports(worker)) {
return adapter;
}
}
return null;
}
/**
* 获取所有的适配器
*
* @return
*/
private static List<IWorkAdapter> getAllAdapters() {
List<IWorkAdapter> list = new ArrayList<>();
list.add(new CookerAdapter());
list.add(new ProgrammerAdapter());
return list;
}
缺省适配器模式:由适配器模式简化而来,省略了适配器中目标接口,也就是源接口和目标接口相同,源接口为接口,目标接口为类。
典型的缺省适配器模式:JavaEE规范中的Servlet接口与GenericServlet抽象类。
Servlet接口中包含五个抽象方法,而其中的service()方法才是用于实现业务逻辑的、必须要实现的方法,另外四个方法一般都是空实现,或简单实现。
GenericServlet抽象类实现了Servlet接口的service()方法以外的另外四个方法,所有自定义的Servlet只需要继承GenericServlet抽象类,实现service()方法即可。无需再实现Servlet接口了。