适配器模式

在现实生活中,经常出现两个对象因接口不兼容而不能在一起工作的实例,这时需要第三者进行适配。例如,讲中文的人同讲英文的人对话时需要一个翻译,用直流电的笔记本电脑接交流电源时需要一个电源适配器,用220V电压给手机充电的时候需要手机充电器将220V转为手机可以充电的5V等。

在软件设计中也可能出现:需要开发的具有某种业务功能的组件在现有的组件库中已经存在,但它们与当前系统的接口规范不兼容,如果重新开发这些组件成本又很高,这时用适配器模式能很好地解决这些问题。

适配器工作原理

  1. 适配器模式:将一个类的接口转成另一种接口,让原本接口不兼容的类可以兼容
  2. 从用户角度看不到被适配者,是解耦的
  3. 用户调用适配器转化出来的目标接口方法,适配器再度调用被适配者的相关接口方法
  4. 用户收到反馈结果,感觉只是和目标接口交互

1、类适配器模式

基本介绍:

Adapter类,通过继承src类,实现dst类接口,完成src-->dst的适配

手机充电器案例

插座电压(220V),手机充电需要的电压(5V),充电器(将220V转为5V)

充电器就相当于Adapte,220V是src,5V是dst

代码实现:

被适配者类(Voltage220V):

/**
 * 被适配者类
 */
public class Voltage220V {

	protected int outPut220V() {
		int src = 220;
		System.out.println("当前电压:" + src + "V");
		return src;
	}
}

目标类(IVoltage5V):

/**
 * 目标类
 */
public interface IVoltage5V {
	
	public int outPut5V();
}

适配器类(VolategeAdapter):

/**
 * 适配器类
 */
public class VolategeAdapter extends Voltage220V implements IVoltage5V{

	public int outPut5V() {
		int srcV = outPut220V();
		int dstV = srcV / 44 ;
		System.out.println("电压处理,当前电压:" + dstV + "V");
		return dstV;
	}

}

使用者类(Phone):

public class Phone {

	public void charging(IVoltage5V iVoltage5V) {
		
		if(iVoltage5V.outPut5V() == 5){
			System.out.println("电压匹配成功,开始充电");
		}
		
	}
}

客户端类(Client):

/**
 * 客户端类
 */
public class Client {

	public static void main(String[] args) {
		
		System.out.println("=== 类适配器模式 ===");
		Phone phone = new Phone();
		phone.charging(new VolategeAdapter());
		
	}

}

类适配器的注意事项和细节:

  • Java是单继承机制,所以类适配器需要继承src类这一点算一个缺点,因为dst必须是接口,有一定局限性
  • src类的方法必须在Adapter类中暴露出来,增加了使用成本
  • 优点:由于继承了src类,所以它可以根据需求重写src类的方法,是的Adapter的灵活性增强了

针对于类适配器必须继承src类的缺点,提出改进方案,即对象适配器

 

2、对象适配器

基本介绍:

    对象适配器是适配器没模式中最常用的一种,基本思路与类适配器相同,只是将Adapter类做修改,不是继承src类,而是持有src类的实例,从而解决兼容性问题。即持有src类,实现dst接口,完成src-->dst的适配。

代码实现:(在上述类适配器的基础上修改)

为了对比类适配器模式,这里我们新增一个类 ( VoltageAdapter2 ) :

/**
 * 适配器类
 */
public class VolategeAdapter2 implements IVoltage5V {

	// 持有 Voltage220V 类 ,不是继承
	private Voltage220V voltage220V;

	// 通过构造器传入 Voltage220V 实例
	public VolategeAdapter2(Voltage220V voltage220v) {
		this.voltage220V = voltage220v;
	}

	public int outPut5V() {
		int srcV = voltage220V.outPut220V();
		int dstV = srcV / 44;
		System.out.println("电压处理,当前电压:" + dstV + "V");
		return dstV;
	}

}

修改客户端类(Client):

/**
 * 客户端类
 */
public class Client {

	public static void main(String[] args) {
		
		System.out.println("=== 类适配器模式 ===");
		Phone phone = new Phone();
		phone.charging(new VolategeAdapter());
		
		System.out.println("=== 对象适配器模式 ===");
		Phone phone1 = new Phone();
		phone1.charging(new VolategeAdapter2(new Voltage220V()));
		
	}

}

对象适配器模式注意事项和细节

  • 对象适配器和类适配器其实算是同一种思想,只是实现方法不同
  • 对象适配器使用组合代替继承,解决了类适配器必须继承src类的局限性问题,也不再要求dst是接口
  • 使用成本低,更加灵活。推荐使用

 

3、接口适配器模式(也叫缺省适配器模式)

基本介绍:

    当不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并为该接口中的每一个方法提供一个默认实现(空方法),那么该抽象类的子类可以有选择的覆盖父类的某些方法来实现需求,适用于一个接口不想使用其所有的方法的情况

Interface4:

public interface Interface4 {
	
	public void m1();
	public void m2();
	public void m3();
	public void m4();
	
}

AbsAdapter:

/**
 *实现接口,空实现所有方法
 */
public class AbsAdapter implements Interface4{

	@Override
	public void m1() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void m2() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void m3() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void m4() {
		// TODO Auto-generated method stub
		
	}

}

 A:

public class A {
	
	public static void main(String[] args) {
		
		AbsAdapter absAdapter = new AbsAdapter(){
			public void m1(){
				System.out.println("我实现了m1方法");
			}
		};
		
		absAdapter.m1(); // 需要用到的方法就自己重写父类的空实现
		
		absAdapter.m2(); // 虽然可以调用其他方法但是都是空实现   (方法m3/m4 同理)
		
	}

}

4、双向适配器模式

实现代码:

//客户端代码
public class TwoWayAdapterTest {
	public static void main(String[] args) {
		System.out.println("目标通过双向适配器访问适配者:");
		TwoWayAdaptee adaptee = new AdapteeRealize();
		TwoWayTarget target = new TwoWayAdapter(adaptee);
		target.request();
		System.out.println("-------------------");
		System.out.println("适配者通过双向适配器访问目标:");
		target = new TargetRealize();
		adaptee = new TwoWayAdapter(target);
		adaptee.specificRequest();
	}
}

//目标接口
interface TwoWayTarget {
	public void request();
}

// 适配者接口
interface TwoWayAdaptee {
	public void specificRequest();
}

// 目标实现
class TargetRealize implements TwoWayTarget {
	public void request() {
		System.out.println("目标代码被调用!");
	}
}

// 适配者实现
class AdapteeRealize implements TwoWayAdaptee {
	public void specificRequest() {
		System.out.println("适配者代码被调用!");
	}
}

// 双向适配器
class TwoWayAdapter implements TwoWayTarget, TwoWayAdaptee {
	private TwoWayTarget target;
	private TwoWayAdaptee adaptee;

	public TwoWayAdapter(TwoWayTarget target) {
		this.target = target;
	}

	public TwoWayAdapter(TwoWayAdaptee adaptee) {
		this.adaptee = adaptee;
	}

	public void request() {
		adaptee.specificRequest();
	}

	public void specificRequest() {
		target.request();
	}
}

 

拓展:SpringMVC中的HandlerAdapter就用到了适配器模式

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值