实例讲解JAVA 适配器模式

 更新时间:2020年06月24日 17:06:18   作者:认真对待世界的小白  
这篇文章主要介绍了JAVA 适配器模式的的相关资料,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下

在讲述这个模式之前,我们先看一个案例:中国球员去NBA打篮球

中国球员去NBA打篮球,可是他不懂英语,所以听不懂教练安排的战术,所以现在有三种解决方式

1、球员学会英语。2、教练学会中文。3、请个翻译。

1和2是长久之计,但不能解决迫在眉睫的问题。请个翻译是短暂的更好的选择。

放在软件设计层面上,这就叫做适配器模式。https://www.jb51.net/article/189484.htm

将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

在软件开发中,也就是系统的数据和行为都正确,但接口不符时,我们应该考虑用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配,适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况。

在 GoF 的设汁模式中,对适配器模式讲了两种类型,类适配器模式和对象适配器模式,由于类适配器模式通过多重继承对一个接口与另一个接口进行匹配,而JAVA语言不支持多重继承,也就是一个类只有一个父类,所以我们这里主要讲的是对象适配器。

Target(这是客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口)代码如下:

public class Target {
 public void request() {
 System.out.println("普通请求");
 }
}

Adaptee(需要适配的类)代码如下:

public class Adaptee {
 public void specialRequest(){
 System.out.println("特殊请求");
 }
}

Adapter(通过在内部包装一个Adaptee对象,把原接口转换成目标接口)代码如下:

public class Adapter extends Target{
 private Adaptee adaptee = new Adaptee();//建立一个私有的Adaptee对象
 
 @Override
 public void request() {
 //这样就可以把表面上调用request()方法变成实际调用的specialRequest()
 adaptee.specialRequest();
 }
}

测试方法

public class Test {
 public static void main(String[] args) {
     //对main方法来说,调用的就是Target的request() 
     Target target = new Target();
 target.request();
 }
}

看起来是不是很简单,是不是跟一句俗语很像“挂羊头卖狗肉”。

何时使用适配器模式?

在想使用一个已经存在的类,但如果它的接口,也就是它的方法和你的要求不相同时,就应该考虑用适配器模式。两个类所做的事情相同或相似,但是具有不同的接口时要使用它。而且由于类都共亨同一个接口,代码可以统一调用同一接口就行了,这样应该可以更简单、更直接、更紧凑。

其实用适配器模式也是无奈之举,很有点‘亡羊补牢'的感觉,没办法呀,是软件就有维护的一天,维护就有可能会因不同的开发人员、不同的产品、不同的厂家而造成功能类似而接口不同的情况,此时就是适配器模式大展拳脚的时候了。

现在把教练给球员们分配任务的例子用适配器模式实现

球员类

public abstract class Player {
 protected String name;
 public Player(String name) {
 this.name = name;
 }
 //进攻和防守方法
 public abstract void attack();
 public abstract void defense();
}

后卫、中锋、前锋类

//前锋
public class Forwards extends Player {
 public Forwards(String name) {
 super(name);
 }
 @Override
 public void attack() {
 System.out.println("前锋:"+name+"进攻");
 }
 @Override
 public void defense() {
 // TODO Auto-generated method stub
 System.out.println("前锋:"+name+"防守");
 }
}
//中锋
public class Center extends Player {
 public Center(String name) {
 super(name);
 }
 @Override
 public void attack() {
 System.out.println("中锋:"+name+"进攻");
 }

 @Override
 public void defense() {
 // TODO Auto-generated method stub
 System.out.println("中锋:"+name+"防守");
 }
}
//后卫
public class Guards extends Player {
 public Guards(String name) {
 super(name);
 }
 @Override
 public void attack() {
 System.out.println("后卫:"+name+"进攻");
 }
 @Override
 public void defense() {
 // TODO Auto-generated method stub
 System.out.println("后卫:"+name+"防守");
 }
}

测试方法

public class Test {
 public static void main(String[] args) {
 Player peter = new Forwards("peter");
 peter.attack();
 Player mike = new Guards("mike");
 mike.attack();
 
 Player zhangsan = new Center("张三");
 zhangsan.attack();
 zhangsan.defense();
 }
}

输出结果:

前锋:peter进攻
后卫:mike进攻
中锋:张三进攻
中锋:张三防守

球员“张三”不会说英语,需要翻译,用适配器模式完善代码

//外籍中锋
public class ForeignCenter {
 private String name;
 //外籍中锋只懂得中文“进攻”
 public void jingong() {
 System.out.println("中锋:"+name+"进攻");
 }
 //外籍中锋只懂得中文“防守”
 public void fangshou() {
 System.out.println("中锋:"+name+"防守");
 }

 //省略getter、setter方法
}
//翻译者
public class Translator extends Player {
 //声明并实例化一个内部“外籍中锋”对象,表面翻译者与外籍球员有关联
 private ForeignCenter wjzf = new ForeignCenter();
 
 public Translator(String name) {
 super(name);
 wjzf.setName(name);
 }
 
 @Override
 public void attack() {
 //翻译者将attack翻译为jingong 告诉外籍中锋
 wjzf.jingong();
 }

 @Override
 public void defense() {
 //翻译者将defense翻译为fangshou 告诉外籍中锋
 wjzf.fangshou();
 }
}

main方法修改代码如下:

//翻译者
public class Translator extends Player {
 //声明并实例化一个内部“外籍中锋”对象,表面翻译者与外籍球员有关联
 private ForeignCenter wjzf = new ForeignCenter();
 
 public Translator(String name) {
  super(name);
  wjzf.setName(name);
 }
 
 @Override
 public void attack() {
  //翻译者将attack翻译为jingong 告诉外籍中锋
  wjzf.jingong();
 }

 @Override
 public void defense() {
  //翻译者将defense翻译为fangshou 告诉外籍中锋
  wjzf.fangshou();
 }
}

现在就算是张三不懂英文,教练不懂中文,但因为有了翻译者,团队沟通合作成为了可能。

如果能事先预防接口不同的问题,不匹配问题就不会发生:在有小的接口不统一问题发生时,及时重构,问题不至于扩大:只有碰到无法改变原有设计和代码的情况时,才考虑适配。

事后控制不如事中控制,事中控制不如事前控制。

以上就是实例讲解JAVA 适配器模式的详细内容,更多关于JAVA 适配器模式的资料请关注脚本之家其它相关文章!

相关文章

  • Java中字符数组、String类、StringBuffer三者之间相互转换

    Java中字符数组、String类、StringBuffer三者之间相互转换

    这篇文章主要介绍了Java中字符数组、String类、StringBuffer三者之间相互转换,需要的朋友可以参考下
    2018-05-05
  • Java对象转json的方法过程解析

    Java对象转json的方法过程解析

    这篇文章主要介绍了Java对象转json的方法过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • springboot2.3 整合mybatis-plus 高级功能及用法详解

    springboot2.3 整合mybatis-plus 高级功能及用法详解

    这篇文章主要介绍了springboot2.3 整合mybatis-plus 高级功能,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • 基于Java编写一个粽子大作战小游戏

    基于Java编写一个粽子大作战小游戏

    端午节,又称龙舟节、重午节,是中国的传统节日之一,每年农历五月初五庆祝,虽然端午假期已经过去了,小编还是用Java编写了一个粽子大作战小游戏,感兴趣的可以了解一下
    2023-06-06
  • SpringMVC底层执行流程及原理解析

    SpringMVC底层执行流程及原理解析

    这篇文章主要介绍了SpringMVC底层执行流程及原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05
  • SpringBoot+RabbitMQ 实现死信队列的示例

    SpringBoot+RabbitMQ 实现死信队列的示例

    本文主要介绍了SpringBoot+RabbitMQ 实现死信队列的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • 在es中查询null值的操作方法

    在es中查询null值的操作方法

    在我们向es中写入数据时,有些时候数据写入到es中的是null,或者没有写入这个字段,那么这个时候在es中该如何查询出这种为null的数据呢,本文给大家详细讲解,需要的朋友参考下吧
    2023-02-02
  • Java文件拒绝访问问题及解决

    Java文件拒绝访问问题及解决

    这篇文章主要介绍了Java文件拒绝访问问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • Java中Json字符串直接转换为对象的方法(包括多层List集合)

    Java中Json字符串直接转换为对象的方法(包括多层List集合)

    下面小编就为大家带来一篇Java中Json字符串直接转换为对象的方法(包括多层List集合)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-08-08
  • Springboot如何通过流返回文件

    Springboot如何通过流返回文件

    这篇文章主要介绍了Springboot如何通过流返回文件,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03

最新评论