深入理解适配器设计模式(java版本)

2022-07-04 14:35:49 浏览数 (1)

前言:

最近在学习mybatis的源码,发现了里面用了非常多的设计模式,今天就来总结一下从mybatis源码中看到的适配器设计模式。为什么一些经典的优秀的框架能够经久不衰呢?不仅仅是因为他们的功能强大,而是在于源码里面的思想,用到的设计模式非常灵活。这就是我们为什么一定要去阅读一些优秀的开源框架的源码,从源码中理解设计模式会发现比我们从书本上看到的更容易理解,从而是我们更容易思考在我们写代码时什么时候能运用这种模式,这是成为一个架构师的必经之路。例如,mybatis中的日志功能就是灵活的使用了适配器设计模式,mybatis中并没有自己的日志功能,他就是适配了各种第三方的日志(slf4J 、commonsLoging 、 Log4J2、 Log4J、 JdkLog)。好了,废话不多说了,直接适配器设计模式。

1、适配器的解释

适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁,将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

这里举个例子来方便理解,大家都应该见过苹果充电器的数据线和android充电器的数据线(接手机的那一头)是不一样的,android充电线想要给苹果手机充电,是不是需要一个转换头,这个转换头就是充当了一个适配器的角色。

2、uml图

Target:目标角色,期待得到的接口.

Adaptee:适配者角色,被适配的接口.

Adapter:适配器角色,将源接口转换成目标接口.

3,使用场景

当调用双方都不太容易修改的时候,为了复用现有组件可以使用适配器模式,在系统中接入第三方组件的时候经常被使用到。

注意:如果系统中存在过多的适配器,会增加系统的复杂性,设计人员应考虑对系统进行重构

4,实例

我们来模拟一个给苹果手机充电的场景,有下面两个需求

1,使用android充电线给苹果手机充电

2,使用typeC的充电线给苹果手机充电

ICharge .java

代码语言:javascript复制
package adapter;

/**
 * @author hongtaolong
 * 苹果手机充电的统一接口
 */
public interface ICharge {

	void charging();
}

AndroidCharge.java

代码语言:javascript复制
package adapter;

public class AndroidCharge {
	private String name = "android";
	public void androidCharging() {
		System.out.println("正在充电:" name);
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	
}

TypeCCharge .java

代码语言:javascript复制
package adapter;

public class TypeCCharge {

	private String name="typec";
	public void typecCharging() {
		System.out.println("正在充电:" name);
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	
}

AndroidChargeAdapter.java

代码语言:javascript复制
package adapter;

/**
 * @author hongtaolong
 * 适配android充电线给苹果手机充电
 */
public class AndroidChargeAdapter implements ICharge{

	private AndroidCharge mAndroidCharge;
	public AndroidChargeAdapter(AndroidCharge androidCharge) {
		// TODO Auto-generated constructor stub
		this.mAndroidCharge = androidCharge;
	}
	@Override
	public void charging() {
		// TODO Auto-generated method stub
		mAndroidCharge.setName("iphone");
		mAndroidCharge.androidCharging();
	}

}

TypeCChargeAdapter .java

代码语言:javascript复制
package adapter;

/**
 * @author hongtaolong
 * 适配typec的充电线,给苹果手机充电
 */
public class TypeCChargeAdapter implements ICharge{

	private TypeCCharge mTypeCCharge;
	public TypeCChargeAdapter(TypeCCharge typeCCharge) {
		// TODO Auto-generated constructor stub
		mTypeCCharge = typeCCharge;
	}
	@Override
	public void charging() {
		// TODO Auto-generated method stub
		mTypeCCharge.setName("iphone");
		mTypeCCharge.typecCharging();
	}

}

TestClient .java

代码语言:javascript复制
package adapter;

public class TestClient {

	public static void main(String[] args) {
		AndroidCharge androidCharge = new AndroidCharge();
		//未适配,只能给android手机充电
		androidCharge.androidCharging();
		TypeCCharge typeCCharge = new TypeCCharge();
		//未适配,只能给typec的设备充电
		typeCCharge.typecCharging();
		
		//适配之后的
		ICharge charge = new AndroidChargeAdapter(androidCharge);
		charge.charging();
		
		charge = new TypeCChargeAdapter(typeCCharge);
		charge.charging();
	}
}

运行结果:

5、适配器模式的优点

谈到优点,先说一下设计模式的几个原则

单一职责原则:一个类或者一个接口只负责唯一项职责,尽量设计出功能单一的接口

依赖倒转原则:高层模块不应该依赖低层模块具体实现,解耦高层与低层。既面向接口编程,当实现发生变化时,只需提供新的实现类,不需要修改高层模块代码

开放-封闭原则:程序对外扩展开放,对修改关闭;换句话说,当需求发生变化时,我们可以通过添加新模块来满足新需求,而不是通过修改原来的实现代码来满足新需求

解析:假如现在又出了一种新的充电线,同样也是无法直接给苹果手机充电,那么我们直接可以增加新的适配器去适配,而不用修改现有的代码,因为修改现有的代码很容易造成牵一发动全身,并且不容易单元测试,程序的扩展性非常差。

单一职责原则就是适配器只起到适配的作用,不用做其他的功能,它和依赖倒转原则(为什么我给上面的例子定义一个统一的ICharge接口)都可以降低程序的耦合性,使得程序的扩展性提高

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/111237.html原文链接:https://javaforall.cn

0 人点赞