适配器模式
将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,适配器模式分为类结构型模式(继承)和对象结构型模式(组合)两种,前者(继承)类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。
别名也可以是Wrapper,包装器
比如有已经定义好的A 和B两个类,之前两个类之间并没有任何关联和交互,此时突然想在A中的某个方法a()调用B中的方法,我们不应该直接在a()方法中添加,这样违反了开闭原则。我们可以创建一个新的适配器类来连接两个类。
适配器模式(Adapter)包含以下主要角色。
目标(Target)接口:可以是抽象类或接口。客户希望直接用的接口
适配者(Adaptee)类:隐藏的转换接口
适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口。
实例:字幕翻译功能
可以进行电影的播放并返回中文字幕。但是现在有日本人想看这个电影,我们又有一个翻译的类,在不改变原播放器类的基础上,我们可以新建一个适配器类组合/继承翻译类,让日本人调用适配器类来观看电影
原类结构
/*** 1、系统原有的接口,可以播放电影,并且返回字幕*/public interface Player {public String play(); //电影播放功能}
/*** 2、系统原有的接口,可以翻译并返回翻译后的内容*/public interface Translate {public String translate(String str);}
/**系统原有实现类,播放电影并返回字幕*/public class MoviePlayer implements Player{@Overridepublic String play() {System.out.println("电影名: 小时代");String str="你好";//第一行字幕并返回return str;}}
/*** 系统原有实现类,可以将中文转换成日文*/public class Zh_JPTranslator implements Translator {@Overridepublic String translate(String str) {if ("你好".equals(str)){return "库你急哇";}if ("什么".equals(str)){return "纳尼";}return "*********";}}
- 通过类结构模式(继承的方式)
public class JpMoviePlayerAdapter extends Zh_JPTranslator implements Player {private Player player;public JpMoviePlayerAdapter(Player player){this.player=player;}@Overridepublic String play() {String content= player.play();String translate = translate(content);return translate;}}
public class MainTest {public static void main(String[] args) {//日本人想看这个电影JpMoviePlayerAdapter adapter=new JpMoviePlayerAdapter(new MoviePlayer());adapter.play();}}
2.通过对象结构型模式(组合的方式)
public class JpMoviePlayerAdapter implements Player {private Player player;private Translator translator=new Zh_JPTranslator(); //这里直接new了出来,可以通过构造函数传也行public JpMoviePlayerAdapter(Player player){this.player=player;}@Overridepublic String play() {String content= player.play();String translate = translator.translate(content);System.out.println(translate);return translate;}}
实现适配器的两种方式
- 类结构模式(继承)

- 对象结构模式(组合)

使用场景
什么场景用到?
Tomcat如何将Request流转为标准Request;
tomcat.Request接口
servlet.Request接口
tomcat === CoyoteAdapte === ServletRequest
Spring AOP中的AdvisorAdapter是什么:增强的适配器
前置、后置、返回、结束 Advisor(通知方法)
底层真的目标方法
Spring MVC中经典的HandlerAdapter是什么;
HelloController.hello() 本身存在的
HandlerAdapter 通过这个适配器,调用下面Servlet中的方法
Servlet.doGet() 本身存在的
SpringBoot 中 WebMvcConfigurerAdapter为什么存在又取消
……
装饰器模式
某个类有一天功能不够用了,想在这个类的上重新增强一样,同样我们不能修改原类中的方法(开闭原则),我们创建一个新的增强类(Wrapper/decorator,适配器也可以叫Wrapper)然后在这个类上进行增强。
装饰器和适配器很像,只不过装饰器是创建了一个类,直接在类中自己对方法增强,而适配器相当于连接两个类,一个类写好的方法可以作用在另一个类上
实例 直播增强
//抖音直播接口public interface ManTikTok {void tiktok();}
//实现类public class LeiFengYangTikTok implements ManTikTok{@Overridepublic void tiktok() {System.out.println("雷丰阳正在直播....");}}
//装饰器接口,专门增强ManTikTok接口的类public interface TikeTokDecorator extends ManTikTok{ //因为需要原方法,在此继承并提供自己的增强方法,在适配器中不需要增强方法,因为在另一个类已经写好了,所以适配器中不用提供这个接口也可以void enable();//提供增强的方法}
public class MeiYanDecorator implements TikeTokDecorator{//被装饰的对象private ManTikTok manTikTok;public MeiYanDecorator(ManTikTok manTikTok){this.manTikTok=manTikTok;}@Overridepublic void tiktok() {enable(); //开启直播前先开启美颜manTikTok.tiktok();}/*** 定义增强功能,装饰器就是在类里直接写,而适配器已经有写好了的,可以直接引入用*/@Overridepublic void enable() {System.out.println("开启了美颜...");}}
使用场景
抽象构件(Component)角色:
定义一个抽象接口以规范准备接收附加责任的对象。
具体构件(ConcreteComponent)角色:
实现抽象构件,通过装饰角色为其添加一些职责。
抽象装饰(Decorator)角色:
继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
具体装饰(ConcreteDecorator)角色:
实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。
