适配模式(Adapter Pattern)
适配器模式的定义
适配器模式:将一个类的接口转换成客户希望的另一个接口。适配器模式让那些接口不兼容的类可以一起工作。
适配器模式的别名为包装器(Wrapper)模式,它既可以作为类结构型模式,也可以作为对象结构型模式。在适配器模式定义中所提及的接口是指广义的接口,它可以表示一个方法或者方法的集合。
适配器模式的结构
类适配器模式结构图:
image-20211127145629618.png活动发劵举例子
//目标接口
public interface AtvSendCoupon {
//目标接口期待的方法
public void sendCouponByAtv();
}
//适配者(源类)
public class SendCouponAdpatee {
public void sendCoupon(){
System.out.println("发劵逻辑(最核心方法)");
}
}
//适配器类(针对活动发劵适配的)
public class AtvSendCouponAdpater extends SendCouponAdpatee implements AtvSendCoupon {
@Override
public void sendCouponByAtv() {
System.out.println("活动发劵的逻辑");
this.sendCoupon();
}
}
//客户端测试
public class Test {
public static void main(String[] args) {
//1.使用 活动适配器
AtvSendCouponAdpater atvSendCouponAdpater = new AtvSendCouponAdpater();
atvSendCouponAdpater.sendCouponByAtv();
}
//活动发劵的逻辑
//发劵逻辑(最核心方法)
}
UXM类图
image-20211127151539484.png适配器模式-扩展
场景需求:
/**
* 需求:
* 1. 退款流程分两种
* a. 通过xxx平台退劵有两个途径;在xxx1退劵,在xxx2退劵(核心流程一样)
* b. yyy退劵(组合劵): 在yyy的退劵(又是核心流程一种)
*
* 实现思路:
* 1. 需要一个 xxx退劵的适配器,和一个yyy退劵的适配器
* 2. 需要把两个对应的适配器在项目启动自动加载进去
* 3. 需要一个派发类,去控制 是执行xxxx的适配器退款逻辑,还是执行yyyy退劵的逻辑
* 4. 不同的客户端测试
* */
image-20211127170929648.png
代码搭建--适配器搭建
- 目标接口2(IPackageRefund-权益包退款接口)
//目标接口2(权益包平台退款)
public interface IPackageRefund {
//客户端期待的退款方法
public void refund();
}
-
目标接口1(IZszRefund-折上折退款接口)
//目标接口1(折上折平台退款) public interface IZszRefund { //客户端期待的退款方法 public void refund(); }
-
适配者-抽象类(AbstractRefundAdaptee--核心方法注册适配器插件)
//适配者 抽象类,作用:自动注册到适配器集合里
public abstract class AbstractRefundAdaptee implements IRefundAdapterPlugin {
//构造函数
public AbstractRefundAdaptee() {
this.register();
}
//自动注册
public interface IRefundAdapterPlugin {
String getAdapterName();
}
private void register() {
// System.out.println("自动注册");
//单例模式调用
AutoRefundAdapterBundleService instance = AutoRefundAdapterBundleService.getInstance();
instance.register(this);
// AutoRefundAdapterBundleService autoRefundAdapterBundleService = new AutoRefundAdapterBundleService();
// autoRefundAdapterBundleService.register(this);
}
}
IRefundAdapterPlugin 退款适配器插件-作用是让每一个子类的适配器定义适配器插件名称
//退款适配器插件
public interface IRefundAdapterPlugin {
String getAdapterName();
}
AutoRefundAdapterBundleService 自动注册退款适配器插件--作用:提供获取已注册插件和注册插件方法
此类使用的单例模式--目的为了客户端测试获取到最新的已注册记录
//自动注册适配器到一个list,并且可以获取所有的适配器
public class AutoRefundAdapterBundleService {
//先定义一个 适配器的集合
private List<IRefundAdapterPlugin> adpaters;
//获取所有的适配器
public List<IRefundAdapterPlugin> getAdpaters() {
return adpaters;
}
//注册适配器到list中
public void register(IRefundAdapterPlugin adapterPlugin) {
if(adpaters == null) {
adpaters = new ArrayList<>();
}
System.out.println("注册适配器--开始");
System.out.println(adapterPlugin);
//适配器注册
if(!adpaters.contains(adapterPlugin)) {
adpaters.add(adapterPlugin);
}
System.out.println("注册适配器--结束");
}
//将此类作成单例模式
public static AutoRefundAdapterBundleService instance;
public AutoRefundAdapterBundleService() {}
public static synchronized AutoRefundAdapterBundleService getInstance() {
if(instance == null) {
instance = new AutoRefundAdapterBundleService();
}
return instance;
}
}
- 不同适配器设置
- 一手劵退款适配器
// 折上折一手劵退款适配器
public class FirstRefundAdapter extends AbstractRefundAdaptee implements IZszRefund {
@Override
public void refund() {
System.out.println("折上折一手劵退款适配器--退款的方法");
}
@Override
public String getAdapterName() {
return "FirstRefundAdapter";
}
}
-
二手劵退款适配器
// 折上折二手劵退款适配器 public class SecondRefundAdapter extends AbstractRefundAdaptee implements IZszRefund { @Override public void refund() { System.out.println("折上折二手劵退款适配器--退款的方法"); } @Override public String getAdapterName() { return "SecondRefundAdapter"; } }
-
权益包退款适配器
// 权益包退款适配器
public class PackageRefundAdapter extends AbstractRefundAdaptee implements IPackageRefund {
@Override
public void refund() {
System.out.println("权益包退款适配器--退款的方法");
}
@Override
public String getAdapterName() {
return "PackageRefundAdapter";
}
}
-
客户端测试验证
public class Test { public static void main(String[] args) { //1. 先注册适配器插件 FirstRefundAdapter firstRefundAdapter = new FirstRefundAdapter(); SecondRefundAdapter secondRefundAdapter = new SecondRefundAdapter(); PackageRefundAdapter packageRefundAdapter = new PackageRefundAdapter(); //2.单例模式查看当前已注册适配器 AutoRefundAdapterBundleService instance = AutoRefundAdapterBundleService.getInstance(); List<IRefundAdapterPlugin> adpaters = instance.getAdpaters(); System.out.println("当前已注册的适配器"); System.out.println(adpaters); //3. 执行不同适配器的方法 firstRefundAdapter.refund(); secondRefundAdapter.refund(); packageRefundAdapter.refund(); } } /** * 需求: * 1. 退款流程分两种 * a. 通过xxx平台退劵有两个途径;在xxx1平台退劵,在xxx2退劵(核心流程一样) * b. yyy退劵(组合劵): 在yyy的退劵(又是核心流程一样) * * 实现思路: * 1. 需要一个xxx退劵的适配器,和一个yyy退劵的适配器 * 2. 需要把两个对应的适配器在项目启动自动加载进去 * 3. 需要一个派发类,去控制 是执行xxxx的适配器退款逻辑,还是执行yyy退劵的逻辑 * 4. 不同的客户端测试 * */
终端打印
注册适配器--开始 com.kuang.demo06_adapter_pattern_more.adpater.FirstRefundAdapter@2503dbd3 注册适配器--结束 注册适配器--开始 com.kuang.demo06_adapter_pattern_more.adpater.SecondRefundAdapter@4b67cf4d 注册适配器--结束 注册适配器--开始 com.kuang.demo06_adapter_pattern_more.adpater.PackageRefundAdapter@7ea987ac 注册适配器--结束 当前已注册的适配器 [com.kuang.demo06_adapter_pattern_more.adpater.FirstRefundAdapter@2503dbd3, com.kuang.demo06_adapter_pattern_more.adpater.SecondRefundAdapter@4b67cf4d, com.kuang.demo06_adapter_pattern_more.adpater.PackageRefundAdapter@7ea987ac] xxx一手劵退款适配器--退款的方法
xxx二手劵退款适配器--退款的方法
yyy退款适配器--退款的方法
**目录结构**
![image-20211127184922578.png](https://img.haomeiwen.com/i25041675/5c0c7d2ebc08b6f5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
## 分配器执行退款
```java
//分配器执行不同退款适配器退款流程--目的:方便客户端不同的调度使用
public class RefundDispatcher extends AutoRefundAdapterBundleService {
private String adapterName = "";//适配器插件名称
//执行退款流程
public void doRefund(Integer type) {
//模拟一个区分逻辑
if(type == 1) {
adapterName = "FirstRefundAdapter";
} else if(type == 2) {
adapterName = "SecondRefundAdapter";
} else if(type == 3) {
adapterName = "PackageRefundAdapter";
}
//单例模式获取对象
AutoRefundAdapterBundleService instance = AutoRefundAdapterBundleService.getInstance();
List<IRefundAdapterPlugin> adpaters = instance.getAdpaters();
adpaters.stream().forEach(adpater -> {
try {
//反射相关知识
Class<? extends IRefundAdapterPlugin> aClass = adpater.getClass();
Method getAdapterName = aClass.getDeclaredMethod("getAdapterName");
String currentName =(String) getAdapterName.invoke(adpater.getClass().newInstance());
System.out.println(currentName);
Method refund = aClass.getDeclaredMethod("refund");
if(adapterName.equals(currentName)) {
refund.invoke(adpater.getClass().newInstance());
}
// if(adpater instanceof IZszRefund) {
// //如果是xxx的适配器
// if(adpater instanceof FirstRefundAdapter) {
// //如果是xxx的一手退款适配器
// }
// if(adpater instanceof SecondRefundAdapter) {
// //如果是xxx的一手退款适配器
// }
//
// }
// if(adpater instanceof IPackageRefund) {
// //如果是yyy的适配器
//
// }
} catch (Exception e) {
e.printStackTrace();
}
});
}
}
测试验证--通过分配器可以不同切换对应适配器的退款逻辑
注册适配器--开始
com.kuang.demo06_adapter_pattern_more.adpater.FirstRefundAdapter@470e2030
注册适配器--结束
注册适配器--开始
com.kuang.demo06_adapter_pattern_more.adpater.SecondRefundAdapter@33833882
注册适配器--结束
注册适配器--开始
com.kuang.demo06_adapter_pattern_more.adpater.PackageRefundAdapter@e2d56bf
注册适配器--结束
当前已注册的适配器
[com.kuang.demo06_adapter_pattern_more.adpater.FirstRefundAdapter@470e2030, com.kuang.demo06_adapter_pattern_more.adpater.SecondRefundAdapter@33833882, com.kuang.demo06_adapter_pattern_more.adpater.PackageRefundAdapter@e2d56bf]
注册适配器--开始
com.kuang.demo06_adapter_pattern_more.adpater.FirstRefundAdapter@7a92922
注册适配器--结束
FirstRefundAdapter
注册适配器--开始
com.kuang.demo06_adapter_pattern_more.adpater.FirstRefundAdapter@71f2a7d5
注册适配器--结束
xxx一手劵退款适配器--退款的方法
网友评论