1.适配器模式(Adapter)的定义
- 将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
- 适配器模式分为:类适配器模式、对象适配器模式、接口适配器模式。
2.适配器模式的主要优缺点
优点:
- 客户端通过适配器可以透明地调用目标接口。
- 复用了现存的类,程序员不需要修改原有代码而重用现有的适配者类。
- 将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。
缺点:
- 对类适配器来说,更换适配器的实现过程比较复杂。
3.适配器模式主要角色
- 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
- 适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
- 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
4.适配器模式结构
- 类适配器模式结构图
- 对象适配器模式结构图
5.适配器模式的实现
5.1 类适配器模式实现,已播放电影及切换电影为例
- 创建美剧电影目标接口
package com.lw.designpattern.adapter.classadapter; /** * @Classname AmericanMovieTarget * @Description 美剧电影目标接口 * @Author lw * @Date 2019-12-26 12:58 */ public interface AmericanMovieTarget { /** * 播放美剧 * */ public void playAmericanMovie(); }
- 创建韩剧适配者接口
package com.lw.designpattern.adapter.classadapter; /** * @Classname KoreanDramasAdaptee * @Description 韩剧适配者接口 * @Author lw * @Date 2019-12-26 13:08 */ public interface KoreanDramasAdaptee { /** * 播放韩剧 */ public void playKoreanDramas(); }
- 创建韩剧适配者接口实现
package com.lw.designpattern.adapter.classadapter; /** * @Classname KoreanDramasAdapteeImpl * @Description 韩剧适配者接口实现 * @Author lw * @Date 2019-12-26 13:03 */ public class KoreanDramasAdapteeImpl implements KoreanDramasAdaptee { @Override public void playKoreanDramas(){ System.out.println("正在播放韩剧。。。。。。"); } }
- 创建电影适配器类
package com.lw.designpattern.adapter.classadapter; /** * @Classname ClassMovieAdapter * @Description 电影适配器 * @Author lw * @Date 2019-12-26 13:01 */ public class ClassMovieAdapter extends KoreanDramasAdapteeImpl implements AmericanMovieTarget { @Override public void playAmericanMovie() { System.out.println("正在播放美剧。。。。。。"); System.out.println("开始切换。。。。。。"); playKoreanDramas(); } }
- 单元测试
/** * 适配器模式-类适配器 */ @Test public void testClassAdapter(){ AmericanMovieTarget americanMovie = new ClassMovieAdapter(); americanMovie.playAmericanMovie(); }
打印结果
5.2 对象适配器模式实现,已播放电影及切换电影为例
- 创建电影适配器类,相对于类适配器模式实现,稍作改动
package com.lw.designpattern.adapter.objectadapter; import com.lw.designpattern.adapter.classadapter.AmericanMovieTarget; import com.lw.designpattern.adapter.classadapter.KoreanDramasAdaptee; /** * @Classname ObjectMovieAdapter * @Description 电影适配器 * @Author lw * @Date 2019-12-26 13:01 */ public class ObjectMovieAdapter implements AmericanMovieTarget { private KoreanDramasAdaptee koreanDramas; public ObjectMovieAdapter(KoreanDramasAdaptee koreanDramas){ this.koreanDramas = koreanDramas; } @Override public void playAmericanMovie() { System.out.println("正在播放美剧。。。。。。"); System.out.println("开始切换。。。。。。"); koreanDramas.playKoreanDramas(); } }
- 单元测试
/** * 适配器模式-对象适配器 */ @Test public void testObjectAdapter(){ AmericanMovieTarget americanMovie = new ObjectMovieAdapter(new KoreanDramasAdapteeImpl()); americanMovie.playAmericanMovie(); }
打印结果
5.3接口适配器模式实现,已播放电影及切换电影为例
- 创建电影目标接口类
package com.lw.designpattern.adapter.interfaceadpter; /** * @Classname MovieTarget * @Description 电影目标接口 * @Author lw * @Date 2019-12-26 13:18 */ public interface MovieTarget { /** * 播放美剧 * */ public void playAmericanMovie(); /** * 播放韩剧 */ public void playKoreanDramas(); }
- 创建电影适配者抽象类,实现MovieTarget接口
package com.lw.designpattern.adapter.interfaceadpter; /** * @Classname AbstractMovieAdaptee * @Description 电影适配者抽象类 * @Author lw * @Date 2019-12-26 13:19 */ public abstract class AbstractMovieAdaptee implements MovieTarget { @Override public void playAmericanMovie() { } @Override public void playKoreanDramas() { } }
- 创建电影适配器类
package com.lw.designpattern.adapter.interfaceadpter; /** * @Classname InterfaceMovieAdapter * @Description 电影适配器 * @Author lw * @Date 2019-12-26 13:21 */ public class InterfaceMovieAdapter extends AbstractMovieAdaptee { @Override public void playAmericanMovie() { System.out.println("正在播放美剧。。。。。。"); } @Override public void playKoreanDramas() { System.out.println("开始切换。。。。。。"); System.out.println("正在播放韩剧。。。。。。"); } }
- 单元测试
/** * 适配器模式-接口适配器 */ @Test public void testInterfacaAdapter(){ InterfaceMovieAdapter koreanDramasAdapter = new InterfaceMovieAdapter(); koreanDramasAdapter.playAmericanMovie();; koreanDramasAdapter.playKoreanDramas(); }
打印结果
6.适配器模式的应用场景
- 以前开发的系统存在满足新系统功能需求的类,但其接口同新系统的接口不一致。
- 使用第三方提供的组件,但组件接口定义和自己要求的接口定义不同。