1.解析
定义 :
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作;
宗旨 :
保留现有类所提供的服务,向客户提供接口,以满足客户的期望。
分类 :
(1)类适配器:
当客户在接口中定义了他期望的行为时,我们就可以应用适配器模式,提供一个实现该接口的类,并且扩展已有的类,通过创建子类来实现适配。
下面是类适配器的UML图:
(2)对象适配器:
对象适配器”通过组合除了满足“用户期待接口”还降低了代码间的不良耦合。在工作中推荐使用“对象适配”。
下面是对象适配器的UML图:
(3) 缺省适配器模式:
缺省适配器模式是一种特殊的适配器模式,但这个适配器是由一个抽象类实现的,并且在抽象类中要实现目标接口中所规定的所有方法,但很多方法的实现都是“平庸”的实现,也就是说,这些方法都是空方法。而具体的子类都要继承此抽象类。
2.实例
背景 :
接着我们在观察者模式中举得例子的场景 , 随着营业模式的改变,迎来了很多外国游客的青睐.所以 在钱币结算上 我们需要做些换算工作 : 结算的是人民币 , 外国支付的是本国的钱币 !! 在这里举三个例子 : 100元人民币 , 美国人支付多少美元, 韩国人支付多少韩元, 岛国人 支付 多少日元 .
人民币换算接口实现
public interface RMBInterFace {
/**
* 定义人民币接口 实现 : 兑换多少 美元 , 韩元 , 日元
*/
double huiMeiYuan(double rmb);
double huiHanYuan(double rmb);
double huiDaoYuan(double rmb);
}
人民币适配类实现
public class RMBAdaptee {
public double huiHanYuan(double rmb) {
return 0;
}
public double huiDaoYuan(double rmb) {
return 0;
}
public double huiMeiYuan(double rmb) {
return 0;
}
}
1.问题引入
public class MeiGuoPerson implements RMBInterFace{
/**
* 角色 : 美国人
* 任务 : 消费后,需要支付多少美元
* 解释 : 美国人在中国的餐馆中消费,故结算的是rmb , 需要支付的美元
*
* 问题 : 这个美国人类想要使用RMB接口中的美元换算方法,需要实现RMB接口,
* 但是实现了,RMB接口中实现了各个国家的钱币换算方法,美国人这里只想要美元换算的方法实现;
*
* 解决 : 类适配器
*
*/
@Override
public double huiMeiYuan(double rmb) {
//仅仅使用 换算美元的
return rmb*0.1565;
}
@Override
public double huiHanYuan(double rmb) {
//没有使用
return 0;
}
@Override
public double huiDaoYuan(double rmb) {
// 没有使用
return 0;
}
}
2 . 类适配器实现 美元换算
public class MeiGuoPersonAdapter extends RMBAdaptee implements RMBInterFace {
/**
* 类适配器实现 美国人适配器实现 : 将 rmb 换算为 美元
*
*/
@Override
public double huiMeiYuan(double rmb) {
return rmb * 0.1565;
}
}
3 . 对象适配器实现 : 韩元换算
public class HanGuoPersonAdapter implements RMBInterFace{
/**
* 对象适配器实现
* 韩元换算
*
*/
private RMBAdaptee adaptee;
public HanGuoPersonAdapter(RMBAdaptee adaptee) {
this.adaptee=adaptee;
}
@Override
public double huiHanYuan(double rmb) {
return adaptee.huiHanYuan(rmb);
}
@Override
public double huiMeiYuan(double rmb) {
//没有使用
return 0;
}
@Override
public double huiDaoYuan(double rmb) {
//没有使用
return 0;
}
}
4 . 缺省适配器实现
(1) 适配类 为 抽象类 实现 目标换算接口
public abstract class RMBAdaptee1 implements RMBInterFace{
@Override
public double huiMeiYuan(double rmb) {
return rmb * 0.1565;
}
@Override
public double huiHanYuan(double rmb) {
return rmb * 180.6271;
}
@Override
public double huiDaoYuan(double rmb) {
return rmb * 19.1616;
}
}
(2) 实现岛国日元 换算
public class DaoPersonAdapter extends RMBAdaptee1 {
/**
* 岛国 适配器
* 日元换算
* 重写父类方法 ,即可
*/
@Override
public double huiDaoYuan(double rmb) {
return super.huiDaoYuan(rmb);
}
}
5.测试
/**
*
*
* 钱币换算 ,外汇
* 1人民币元=19.1616日元
* 1人民币元=0.1035英镑
* 1人民币元=0.1468欧元
* 1人民币元=180.6271韩元
* 1人民币元=0.1565美元
* 1人民币元=1.2131港元
* 1人民币元=5.0946新台币
* 1人民币元=0.2215新加坡元
*
* 适配器模式 :
*
*
*
*/
public static void main(String[] args) {
//类适配器
RMBInterFace adapter=new MeiGuoPersonAdapter();
double d=adapter.huiMeiYuan(100);
System.out.println(d);
}
3.使用场景
(1) 使用一个已经存在的类,而它的接口不符合你的需求。
(2) 创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。
(3)(仅适用于对象Adapter )你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。
4.总结
使用的前提:
1.接口中规定了所有要实现的方法
2.但一个要实现此接口的具体类,只用到了其中的几个方法,而其它的方法都是没有用的。
实现方法 :
1.用一个抽象类实现已有的接口,并实现接口中所规定的所有方法,这些方法的实现可以都是“平庸”实现—-空方法;但此类中的方法是具体的方法,而不是抽象方法,否则的话,在具体的子类中仍要实现所有的方法,这就失去了适配器本来的作用。
2.原本要实现接口的子类,只实现1中的抽象类即可,并在其内部实现时,只对其感兴趣的方法进行实现。
注意事项 :
1.充当适配器角色的类就是:实现已有接口的抽象类
2.为什么要用抽象类:
此类是不要被实例化的。而只充当适配器的角色,也就为其子类提供了一个共同的接口,但其子类又可以将精力只集中在其感兴趣的地方。