当前位置: 首页 > news >正文

Java设计模式之结构型—适配器模式

Java中最常用的设计模式-CSDN博客

类适配器(使用继承)

目标接口

// 客户期望的 5V 直流电
public interface Dc5V {int output5V();
}

被适配者

// 家里只有 220V 交流电
public class Ac220V {public int output220V() {System.out.println("输出交流 220V");return 220;}
}

适配器

// 用“继承”把 220V 转成 5V
public class PowerAdapter extends Ac220V implements Dc5V {@Overridepublic int output5V() {int src = output220V();      // 拿到 220Vint dst = src / 44;          // 降压System.out.println("输出直流 5V");return dst;}
}

测试

public class Main {public static void main(String[] args) {Dc5V dc5V = new PowerAdapter();dc5V.output5V();   // 客户只关心 Dc5V 接口}
}

对象适配器(使用组合/委派,推荐)

目标接口 & 被适配者同上,不再重复。

适配器

// 用“组合”把 220V 转成 5V
public class PowerObjectAdapter implements Dc5V {private final Ac220V ac220V;   // 组合优于继承public PowerObjectAdapter(Ac220V ac220V) {this.ac220V = ac220V;}@Overridepublic int output5V() {int src = ac220V.output220V();int dst = src / 44;System.out.println("输出直流 5V");return dst;}
}

测试

public class Main {public static void main(String[] args) {Dc5V dc5V = new PowerObjectAdapter(new Ac220V());dc5V.output5V();}
}

接口适配器(缺省适配器 / 抽象适配器)

当接口方法太多,而客户只想实现其中 1~2 个时,用抽象类先空实现全部方法。

目标接口

public interface AllEventListener {void onClick();void onDoubleClick();void onLongPress();
}

抽象适配器

public abstract class MouseAdapter implements AllEventListener {public void onClick()      { /* 空实现 */ }public void onDoubleClick() { /* 空实现 */ }public void onLongPress()   { /* 空实现 */ }
}

具体使用者

public class MyMouseListener extends MouseAdapter {@Overridepublic void onClick() {System.out.println("我只关心单击事件");}
}

测试

public class Main {public static void main(String[] args) {AllEventListener listener = new MyMouseListener();listener.onClick();          // 只触发单击}
}
  • 类适配器:继承被适配者,简单但高耦合。

  • 对象适配器:组合被适配者,灵活可复用,推荐。

  • 接口适配器:抽象类空实现大接口,子类按需覆写,解决“接口污染”。

RecyclerView.Adapter

RecyclerView.Adapter 使用的是 对象适配器(Object Adapter) 这一经典形式

为什么这样归类

  1. 它通过 组合 而非继承来持有并操作“被适配的数据源”:
    你把任何 List<T>(或其它数据结构)组合进自定义的 Adapter 里,Adapter 再把它“适配”成 RecyclerView 能识别的 ViewHolder 序列。

  2. 没有修改数据源类本身,也没有要求数据源继承任何父类;Adapter 只实现 RecyclerView.Adapter 这一“目标接口”,把数据→视图的转换细节封装在 onBindViewHolder() 等方法中。

  3. 如果数据源接口不兼容(例如从数据库 Cursor 到对象模型),再包一层 对象适配器 即可,同样采用组合方式。

简记:
RecyclerView.Adapter = 典型的 对象适配器模式(组合 + 委派)。

RecyclerView.Adapter在RecyclerView中的调用

把 RecyclerView 和 Adapter 的交互画成一条 时间线,你就能一眼看清 “Adapter 是在哪些时机、被谁、以什么顺序调用的”。

RecyclerView
   ├─ LayoutManager      (测量/布局)
   ├─ Recycler           (ViewHolder 缓存池)
   └─ Adapter            (数据 & ViewHolder 工厂)

首次布局
┌────────────┐                       ┌──────────────┐
│ getItemCount│ ←──  LayoutManager ──┤  onMeasure   │
└────┬───────┘                       └──────────────┘
     │                             ┌────────────────┐
     │ 没有缓存                    │ onLayoutChildren│
     ↓                             └──────┬─────────┘
┌────────────┐                           │
│onCreateVH  │ ←── RecyclerView ─────────┘
└────┬───────┘
     │ 得到空壳 ViewHolder
     ↓
┌────────────┐
│onBindVH    │ ←── RecyclerView(把数据塞进壳里)
└────────────┘

  • LayoutManager 是“导演”,它决定什么时候需要 ViewHolder、需要多少。

  • RecyclerView 是“中介”,把 LayoutManager 的需求翻译成对 Adapter 的调用。

  • Adapter 只负责两件事:

    1. 告诉你“一共有多少条”(getItemCount)

    2. 按需生产 & 绑定 ViewHolder(onCreateViewHolder / onBindViewHolder)

RecyclerView.Adapter的onCreateViewHolder是适配器模式,onBindViewHolder观察者模式

  1. onCreateViewHolder → 体现“适配器模式”
    职责:把“数据层”无法直接使用的布局/视图,转换成 RecyclerView 需要使用的 ViewHolder
    这正是适配器模式的本质:接口转换——把 LayoutInflater.inflate() 得到的原始 View,转换成符合 RecyclerView 接口要求的 ViewHolder

  2. onBindViewHolder → 体现“观察者模式(或更广义的数据绑定)”
    职责:当数据源(被观察者)发生变化时,由 RecyclerView 框架主动回调 Adapter,把最新数据“推”给对应的 ViewHolder
    虽然 RecyclerView 内部并没有显式使用 java.util.Observable/Observer,但“数据源变化 → notifyXXX → 系统回调 onBindViewHolder”这一套流程,完全符合 观察者模式 的“发布-订阅”思想:
    • 数据是“被观察者”
    • Adapter/ViewHolder 是“订阅者”
    • notifyItemRangeChanged 等方法就是“发布事件”

一句话总结

  • onCreateViewHolder:完成 视图→ViewHolder 的适配,属于 适配器模式 的具体实现点。

  • onBindViewHolder:完成 数据→视图的同步,体现了 观察者模式 的“推数据”行为。

http://www.xdnf.cn/news/1443691.html

相关文章:

  • 需求调研的核心目标
  • 并发编程——14 线程池参数动态化
  • 前端自动化打包服务器无法安装高版本 Node.js v22 问题解决
  • 京东商品评论API接口概述,json数据返回
  • 51单片机:发光二极管与动态数码管控制
  • 迅为RK3568开发板体验OpenHarmony—烧写镜像-安装驱动
  • dumpsys alarm 简介
  • 关于kafka:consumer_offsets日志不能自动清理,设置自动清理规则
  • Trae x Vizro:低代码构建专业数据可视化仪表板的高效方案
  • 小迪web自用笔记25
  • 年成本下降超80%,银行数据治理与自动化应用实录
  • DS1202示波器的使用教程笔记
  • 【C++八股文】数据结构篇
  • 【Python-Day 42】解锁文本处理神技:Python 正则表达式 (Regex) 从入门到实战
  • FPGA离群值剔除算法
  • wpf 自定义输入ip地址的文本框
  • Linux之shell-awk命令详解
  • Jenkins 可观测最佳实践
  • Jenkins和Fastlane的原理、优缺点、用法、如何选择
  • 记录一下node后端写下载https的文件报错,而浏览器却可以下载。
  • nginx配置端口转发(docker-compose方式、包括TCP转发和http转发)
  • C++ 面试高频考点 力扣 162. 寻找峰值 二分查找 题解 每日一题
  • Apache Kafka:现代数据高速公路的设计哲学
  • 嵌入式硬件 - 51单片机2
  • (11)用于无GPS导航的制图师SLAM(二)
  • AI产品经理面试宝典第84天:RAG系统架构设计与优化策略面试指南
  • C#工作流示例(WorkflowCore)
  • 基于Docker和Kubernetes的CI/CD流水线架构设计与优化实践
  • Go语言实战案例-Redis实现用户登录次数限制
  • 基于单片机车内换气温度检测空气质量检测系统Proteus仿真(含全部资料)