【每日学设计模式——结构型模式】 适配器模式

菜鸟教程链接:适配器模式

概念

适配器模式可以理解为通过不修改父类或接口的情况下,通过子类或实现类组合装载了所需扩展接口的适配器(或直接组合所需扩展接口)的方式,让原来的类或接口可以适配于客户端新的场景。该设计模式不应该应用于设计一个类的过程中,而应该在修改历史代码的过程中使用,使在不修改老代码的基础上扩展新的业务场景,体现了 复合大于继承 这一观点。
在这里插入图片描述

优缺点

优点:

  1. 提高了类的复用
  2. 灵活,透明

缺点:

  1. 可能会使类的定义与其运行时体现的功能不一致,系统复杂度提升
  2. 对原有的实现类有侵入
  3. 由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。

适用场景

对老代码做兼容性升级的场景

示例代码

原本的手机只有打电话和发短信功能,只需实现Phone的接口

public class MobilePhone implements Phone{
   @Override
   public void play(String type) {
   		if ("call".equals(type)){
   			this.call()
   		) else if {"message".equals(type)){
   			this.message()
   		}
   }
}

智能机时代来临,我们手机扩展了播放音乐和视屏的功能,那么我们需要在原有类的基础上直接扩展这些功能吗?不需要,因为音乐和视屏都早已存在对应的实现类与接口了,比如mp3已经实现类MusicPlayer的接口,而TV实现了VedioPlayer的接口,我们只需要将这两个类聚合在一个Adaper类里面,然后再我们的MobilePhone里面注入这个Adaper,通过Adaper去调用这些方法。(个人觉得这里适配器其实无所谓是否实现Phone接口了)

public class MobilePhoneAdapter implements Phone{
	private MusicPlayer mp3 = new Mp3();
	private VedioPlay tv = new TV();
   @Override
   public void play(String type) {
   		if ("music".equals(type)){
   			mp3.music()
   		) else if {"vedio".equals(type)){
   			tv.vedio()
   		}
   }
}

然后再将MobilePhoneAdaper注入到原有的MobilePhone里面,即可在原来的接口中聚合新的功能,这一点在某些场景非常重要。

public class MobilePhone implements Phone{
  private MobilePhoneAdapter= new MobilePhoneAdaper();
  @Override
   public void play(String type) {
   		if ("call".equals(type)){
   			this.call()
   		) else if {"message".equals(type)){
   			this.message()
   		}  else {
   			adapter.play(type)
		}
   }
}

如果我们在构造函数中做手法,甚至可以通过构造不同的适配器,让手机实现不同的功能;比如,我可以让播放音乐的功能由同样实现了MusicPlayer接口的mp4而不是mp3实现,即可通过传递接口来决定Adapter的成员变量,而MobilePhone中同理,此时代码成熟度更高了。

public class MobilePhoneAdapter implements Phone{
	private MusicPlayer musicPlayer;
	private VedioPlay vedioPlayer;
	
	public MobilePhoneAdapter(MusicPlayer musicPlayer, VedioPlay vedioPlayer) {
		this.musicPlayer = musicPlayer;
		this.vedioPlayer = vedioPlayer;
	}
   @Override
   public void play(String type) {
   		if ("music".equals(type)){
   			musicPlayer.music()
   		) else if {"vedio".equals(type)){
   			vedioPlayer.vedio()
   		}
   }
}
public class MobilePhone implements Phone{
  	private MobilePhoneAdapter adapter;

	public MobilePhone(MobilePhoneAdapter adapter) {
		this.adapter =adapter;
	}
  @Override
   public void play(String type) {
   		if ("call".equals(type)){
   			this.call()
   		) else if {"message".equals(type)){
   			this.message()
   		}  else {
   			adapter.play(type)
		}
   }
}

使用时

public class TEST {
   public void test(String type) {
		MusicPlayer  musicPlayer = new Mp4();
		MobilePhoneAdapter  adapter = new MobilePhoneAdapter (musicPlayer,new TV());
		Phone phone = new MobilePhone(adapter);
		phone.play("music");
   }
}

也有说法直接用adapter去组合其他接口视作一个实现类,使用时直接调用adapter去执行play方法。单个人认为这种说法并不合适,不仅在adapter中要重复已有实现类的方法,也降低了类的扩展性和清晰结构,而且定义也更加模糊,你用手机玩游戏,而不是你在用手机里的模拟器玩游戏。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值