适配器模式
先看一个案例:
1.1 厨师主业务接口
1 package com.monkey1024.worker; 2 3 // 厨师主业务接口 4 public interface ICooker { 5 6 // 烹饪 7 String cookeing(); 8 9 }
1.2.程序员主业务接口
1 package com.monkey1024.worker; 2 3 // 程序员主业务接口 4 public interface IProgrammer { 5 6 // 编程 7 String programming(); 8 9 }
2.1 京东程序员
1 package com.monkey1024.worker.imp; 2 3 import com.monkey1024.worker.IProgrammer; 4 5 6 // 京东程序员 (实现类) 7 public class JdProgrammer implements IProgrammer { 8 9 @Override 10 public String programming() { 11 return "码农:我能骚出一手好代码"; 12 } 13 14 }
2.2 全聚德厨师
1 package com.monkey1024.worker.imp; 2 3 import com.monkey1024.worker.ICooker; 4 5 // 全聚德厨师 (实现类) 6 public class QjdCooker implements ICooker { 7 8 @Override 9 public String cookeing() { 10 return "厨师:我能烧出一只好鸭子"; 11 } 12 13 }
3 测试类
1 package com.monkey1024.test; 2 3 import com.monkey1024.worker.ICooker; 4 import com.monkey1024.worker.imp.JdProgrammer; 5 import com.monkey1024.worker.imp.QjdCooker; 6 7 public class MyTest { 8 9 public static void main(String[] args) { 10 11 // 雇一个全聚德的厨师 12 ICooker c = new QjdCooker(); 13 14 // 抓一个京东的程序员 15 JdProgrammer p = new JdProgrammer(); 16 17 // 分别做自我技艺介绍 18 19 System.out.println(c.cookeing()); 20 21 System.out.println(p.programming()); 22 23 24 } 25 26 }
运行结果:
厨师:我能烧出一只好鸭子
码农,我能骚出一手好代码
使用一个适配器编程:
1.1 厨师主业务接口
1 package com.monkey1024.worker;
2
3 // 厨师主业务接口
4 public interface ICooker {
5
6 // 烹饪
7 String cookeing();
8
9 }
1.2.程序员主业务接口
1 package com.monkey1024.worker;
2
3 // 程序员主业务接口
4 public interface IProgrammer {
5
6 // 编程
7 String programming();
8
9 }
2.1 京东程序员
1 package com.monkey1024.worker.imp;
2
3 import com.monkey1024.worker.IProgrammer;
4
5
6 // 京东程序员 (实现类)
7 public class JdProgrammer implements IProgrammer {
8
9 @Override
10 public String programming() {
11 return "码农:我能骚出一手好代码";
12 }
13
14 }
2.2 全聚德厨师
1 package com.monkey1024.worker.imp;
2
3 import com.monkey1024.worker.ICooker;
4
5 // 全聚德厨师 (实现类)
6 public class QjdCooker implements ICooker {
7
8 @Override
9 public String cookeing() {
10 return "厨师:我能烧出一只好鸭子";
11 }
12
13 }
3.1 适配器接口
1 package com.monkey1024.adapters;
2
3 // 适配器接口
4 public interface IWorkerAdapter {
5
6 // 形参是Object类型的工作岗位
7 // 你给我传一个什么岗位,我就给你相应的String类型的工作
8 String work(Object worker);
9
10 }
3.2 适配器类
1 package com.monkey1024.adapters.impl;
2
3 import com.monkey1024.adapters.IWorkerAdapter;
4 import com.monkey1024.worker.ICooker;
5 import com.monkey1024.worker.IProgrammer;
6
7
8 // 适配器类!!!
9 public class WorkerAdapter implements IWorkerAdapter {
10
11 @Override
12 public String work(Object worker) {
13
14 // 给工作内容赋值一个 空字符串 。
15 String workContent ="";
16
17 //做判断
18
19 // 判断传过来的对象是不是 一个 厨师类型,是则调用其cookeing()
20 if(worker instanceof ICooker) {
21
22 // 厨师向经理介绍自己的技能
23 workContent =((ICooker) worker).cookeing();
24
25
26 // 判断传递过来的是不是 一个 程序员类型,是则调用其programming()
27 }else if(worker instanceof IProgrammer){
28
29 // 程序员向经理介绍自己的技能
30 workContent =((IProgrammer) worker).programming();
31
32 }else {
33 System.out.println("抱歉,你不是我们要招聘的人才类型");
34
35 }
36
37 return workContent;
38 }
39
40 }
4. 测试类
1 package com.monkey1024.test; 2 3 import com.monkey1024.adapters.IWorkerAdapter; 4 import com.monkey1024.adapters.impl.WorkerAdapter; 5 import com.monkey1024.worker.ICooker; 6 import com.monkey1024.worker.imp.JdProgrammer; 7 import com.monkey1024.worker.imp.QjdCooker; 8 9 public class MyTest { 10 11 public static void main(String[] args) { 12 13 // 雇一个全聚德的厨师 14 ICooker c = new QjdCooker(); 15 16 // 抓一个京东的程序员 17 JdProgrammer p = new JdProgrammer(); 18 19 20 // 建一个Object数组,用于存放 这些 员工们 21 Object[] workers = {c , p}; 22 23 24 // 创建适配器对象 25 IWorkerAdapter adapter = new WorkerAdapter(); 26 27 28 // 循环遍历每个工种对象,让每个工种对象在适配器中逐个进行匹配 29 for (Object worker : workers) { 30 31 32 String workContent = adapter.work(worker); 33 34 // 输出 员工工种 的相应工作内容 35 System.out.println(workContent); 36 37 } 38 39 } 40 41 }
运行结果:
厨师:我能烧出一只好鸭子
码农:我能骚出一手好代码
使用多个适配器编程:(推荐使用这种,因为在后期的框架源码中 使用的就是这种)
1 -2 步骤代码与上个案例的一样.
3.1 总适配器接口
1 package com.monkey1024.adapters; 2 3 // 总适配器接口 4 public interface IWorkerAdapter { 5 6 // 形参是Object类型的工作岗位 7 // 你给我传一个什么工种,我就给你相应的String类型的工作 8 String work(Object worker); 9 10 11 // 判断 工种与适配器是否 对应 12 boolean supports(Object worker); 13 14 }
3.2 厨师适配器类
1 package com.monkey1024.adapters.impl; 2 3 import com.monkey1024.adapters.IWorkerAdapter; 4 import com.monkey1024.worker.ICooker; 5 6 // 厨师适配器类 7 public class CookerAdapter implements IWorkerAdapter { 8 9 @Override 10 public String work(Object worker) { 11 12 // 返回 厨师 对应的工作内容 13 return ((ICooker)worker).cookeing(); 14 15 } 16 17 @Override 18 public boolean supports(Object worker) { 19 20 // 判断 worker是不是 厨师 21 return (worker instanceof ICooker); 22 } 23 24 }
3.3 程序员适配器类
1 package com.monkey1024.adapters.impl; 2 3 import com.monkey1024.adapters.IWorkerAdapter; 4 import com.monkey1024.worker.IProgrammer; 5 6 // 程序员接口 7 public class ProgrammerAdapter implements IWorkerAdapter { 8 9 @Override 10 public String work(Object worker) { 11 //// 返回 程序员 对应的工作内容 12 return ((IProgrammer)worker).programming(); 13 } 14 15 @Override 16 public boolean supports(Object worker) { 17 // 判断工种是不是 程序员 18 return (worker instanceof IProgrammer); 19 } 20 21 }
4. 测试类
1 package com.monkey1024.test; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import com.monkey1024.adapters.IWorkerAdapter; 7 import com.monkey1024.adapters.impl.CookerAdapter; 8 import com.monkey1024.adapters.impl.ProgrammerAdapter; 9 import com.monkey1024.worker.ICooker; 10 import com.monkey1024.worker.imp.JdProgrammer; 11 import com.monkey1024.worker.imp.QjdCooker; 12 13 public class MyTest { 14 15 public static void main(String[] args) { 16 17 // 雇一个全聚德的厨师 18 ICooker c = new QjdCooker(); 19 // 抓一个京东的程序员 20 JdProgrammer p = new JdProgrammer(); 21 22 // 建一个Object数组,用于存放 这些 员工们 23 Object[] workers = {c , p}; 24 25 26 // 循环遍历每个工种对象,让每个工种对象在适配器中逐个进行匹配 27 for (Object worker : workers) { 28 29 // 拿到该 工种对应的适配器 30 // 怎么拿?先拿到所有的适配器,再在其中寻找自己要的 31 IWorkerAdapter adapter= getAdapter(worker); 32 System.out.println(adapter.work(worker)); 33 } 34 35 } 36 37 38 // 根据worker获取相应的适配器对象 39 private static IWorkerAdapter getAdapter(Object worker) { 40 41 // 先拿到所有的适配器 42 List<IWorkerAdapter> adapters = getAllAdapters(); 43 44 // 遍历所有的适配器 45 for (IWorkerAdapter adapter : adapters) { 46 47 // 如果 传递进来的工种 能够 匹配上 对应的 适配器 48 if(adapter.supports(worker)) { 49 50 return adapter; 51 52 } 53 } 54 return null; 55 56 } 57 58 // 获取所有的适配器 59 private static List<IWorkerAdapter> getAllAdapters() { 60 61 // 创建一个list集合 ,用于存放 所有的适配器 62 List<IWorkerAdapter> adapters = new ArrayList<>(); 63 64 // 存放 厨师适配器 65 adapters.add(new CookerAdapter()); 66 67 // 存放 程序员适配器 68 adapters.add(new ProgrammerAdapter()); 69 70 71 // 返回这个List集合 72 return adapters; 73 } 74 75 76 77 }
缺省适配器模式 (是适配器模式的简易版)
缺省适配器模式是由适配器模式简化而来,省略了适配器模式中目标接口,也就是源接口和目标接口相同,源接口为接口,目标接口为类。
典型的缺省适配器模式是 JavaEE 规范中的 Servlet 接口与 GenericServlet 抽象类。
Servlet 接口中包含五个抽象方法,而其中的 service()方法才是用于实现业务逻辑的、必须要实现的方法,另外四个方法一般都是空实现,或简单实现。
GenericServlet 抽象类实现了 Servlet 接口的 service()方法以外的另外四个方法,所以自定义的 Servlet 只需要继承 GenericServlet 抽象类,实现 service()方法即可。无需再实现Servlet 接口了。