介绍:
1、适配器模式将某个类的接口转换成客户端期望的另一种接口表示 2、目的:兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作。其别名为:包装器。 3、属于:结构型模式 4、分3类: 1)类适配器 2)对象适配器 3)接口适配器 5、解耦。用户也只会看到源头和结果。目标 《- 适配器 《- 被适配器者
类适配器
介绍:
1、类适配器模式介绍 基本介绍:Adapter类,通过继承src类,实现dst类接口,完成src -> dst的适配
例子:
//1、统一的播放器接口
interface MediaPlayer {
void play();
}
//2、两种不同的音频播放器
class AdvancedMusicPlayer {
void playAdvancedMusic() {
System.out.println("Playing advanced music");
}
}
class SimpleMusicPlayer {
void playSimpleMusic() {
System.out.println("Playing simple music");
}
}
//3、类适配器。Adapter类,通过继承src类,实现dst类接口,完成src -> dst的适配
class ClassAdapter extends AdvancedMusicPlayer implements MediaPlayer {
@Override
public void play() {
playAdvancedMusic();
}
}
//4、使用类适配器
MediaPlayer classAdapter = new ClassAdapter();
classAdapter.play();
注意事项和细节
1、Java是单继承的,所以类适配器需要继承src类这是一个缺点,因为这要求了dst必须是接口,有局限性 2、src类的方法在Adapter中都会暴露出来,也增加了使用成本 3、由于其继承了src类,所以它可以根据需求重写src类方法,使Adapter灵活性增强了
对象适配器
介绍
1、基本思路和类适配器相同,只是将Adapter类做了修改,不是继承src类,而是持有src类的实例,以解决兼容性问题。 即:持有src类,实现dst类接口,完成src -> dst的适配 2、根据合成复用原则,在系统中尽量使用关联关系代替继承关系
例子
//1、统一的播放器接口
interface MediaPlayer {
void play();
}
//2、两种不同的音频播放器
class AdvancedMusicPlayer {
void playAdvancedMusic() {
System.out.println("Playing advanced music");
}
}
class SimpleMusicPlayer {
void playSimpleMusic() {
System.out.println("Playing simple music");
}
}
//3、对象适配器:Adapter类做了修改,不是继承src类,而是持有src类的实例,以解决兼容性问题。
class ObjectAdapter implements MediaPlayer {
//src类实例
private AdvancedMusicPlayer advancedPlayer;
public ObjectAdapter(AdvancedMusicPlayer advancedPlayer) {
this.advancedPlayer = advancedPlayer;
}
@Override
public void play() {
advancedPlayer.playAdvancedMusic();
}
}
// 4、使用对象适配器
AdvancedMusicPlayer advancedPlayer = new AdvancedMusicPlayer();
SimpleMusicPlayer simplePlayer = new SimpleMusicPlayer();
MediaPlayer objectAdapter = new ObjectAdapter(advancedPlayer);
objectAdapter.play();
注意事项和细节
1、对象适配器和类适配器是同一种思想,只是实现不同。根据合成复用原则,使用组合替代继承,它解决了类适配器必须继承src的局限性问题,也不要求dst必须是接口 2、使用成本更低,更灵活
接口适配器
介绍
1、适配器模式又称缺省适配器模式 2、当不需要全部实现接口提供方法时,可先设计一个抽象类实现接口,并为改接口中每一个方法提供一个默认实现(空方法),那么该抽象类子类可以选择性的覆盖父类方法 3、适用于一个接口不想使用所有方法情况
例子
//1、统一的播放器接口
interface Player {
void play();
void stop();
void pause();
}
//2、创建一个抽象类,实现Player接口(默认空方法实现)
abstract class PlayerAdapter implements Player {
@Override
public void play() {}
@Override
public void stop() {}
@Override
public void pause() {}
}
//3、创建具体的适配器类,只需重写方法即可
class SimplePlayerAdapter extends PlayerAdapter {
@Override
public void play() {
System.out.println("Simple player is playing");
}
}
class AdvancedPlayerAdapter extends PlayerAdapter {
@Override
public void play() {
System.out.println("Advanced player is playing");
}
@Override
public void stop() {
System.out.println("Advanced player is stopped");
}
@Override
public void pause() {
System.out.println("Advanced player is paused");
}
}
//4、接口适配器使用
public class InterfaceAdapterExample {
public static void main(String[] args) {
Player simplePlayer = new SimplePlayerAdapter();
simplePlayer.play();
Player advancedPlayer = new AdvancedPlayerAdapter();
advancedPlayer.play();
advancedPlayer.stop();
advancedPlayer.pause();
}
}
适配器模式在SpringMVC框架应用的源码分析
适配器模式在SpringMVC框架应用的源码剖析
1、SpringMVC中的HandlerAdapter使用到了适配器模式 2、SpringMVC请求处理的流程回顾 3、使用HandlerAdapter的原因分析
模拟实现
1、Controller接口
package com.pxl.testinterface.SpringMVCTest;
public interface Controller {
}
class HttpController implements Controller{
public void doHttpHandler(){
System.out.println("http...");
}
}
class SimpleController implements Controller{
public void doHttpHandler(){
System.out.println("simple...");
}
}
2、适配器处理
package com.pxl.testinterface.SpringMVCTest;
public interface HandlerAdapter {
boolean supports(Object handler);
void handle( Object handler);
}
class SimpleHandlerAdapter implements HandlerAdapter {
public boolean supports(Object handler) {
return handler instanceof SimpleController;
}
public void handle(Object handler) {
((SimpleController)handler).doHttpHandler();
}
}
class HttpHandlerAdapter implements HandlerAdapter {
public boolean supports(Object handler) {
return handler instanceof HttpController;
}
public void handle(Object handler) {
((HttpController)handler).doHttpHandler();
}
}
3、调用方
package com.pxl.testinterface.SpringMVCTest;
import java.util.ArrayList;
import java.util.List;
public class DispatcherServlet {
public static List<HandlerAdapter> handlerAdapterList = new ArrayList<>();
public DispatcherServlet(){
handlerAdapterList.add(new HttpHandlerAdapter());
handlerAdapterList.add(new SimpleHandlerAdapter());
}
public void doDispatch(){
//此处是模拟SpringMVC从request中获得handler对象
//适配器可以获取到希望得Controller
HttpController controller = new HttpController();
//得到对应适配器
HandlerAdapter adapter = getHandler(controller);
adapter.handle(controller);
}
public HandlerAdapter getHandler(Controller controller){
for (HandlerAdapter adapter : this.handlerAdapterList) {
if (adapter.supports(controller)){
return adapter;
}
}
return null;
}
public static void main(String[] args) {
new DispatcherServlet().doDispatch();
}
}
总结
自己的理解:
当客户端调用适配器时,适配器会返回给客户端一个符合客户端期望的接口的类实例。这样客户端就可以通过适配器来获取想要的类,而无需关心具体的实现细节。 精简: 我调用Adapter,Adapter返回给我一个想要的类
注意事项和细节
1、三种命名方式,是根据src是以怎样的形式给到Adapter(在Adapter的形式)来命名 2、 1)类适配器:以类给到,在Adapter里,将src当作类,继承 2)对象适配器:以对象给到,在Adapter里,将src作为对象,持有 3)接口适配器:以接口给到,在Adapter里,将src作为一个接口,实现 3、Adapter模式最大作用:将原本不兼容的接口融合一起工作 4、实际开发中不仅仅是我们将的3种经典形式