当前位置: 首页 > 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.dtcms.com/a/364443.html

相关文章:

  • SQLAlchemy ORM 入门教程
  • Low-Light Image Enhancement via Structure Modeling and Guidance 论文阅读
  • SQLint3 模块如何使用
  • Linux awk命令完全指南:从原理到实战,搞定文本处理难题
  • SQL(window)日志在linux 下查看
  • LangChain实战(十三):Agent Types详解与选择策略
  • 机器学习从入门到精通 - KNN与SVM实战指南:高维空间中的分类奥秘
  • Spring Boot 工程启动时自动执行任务方法
  • 图像正向扭曲反向扭曲
  • 安全测试漫谈:如何利用X-Forwarded-For头进行IP欺骗与防护
  • 停止所有dcoker容器
  • [UT]记录uvm_config_db的错误:get中的第二个参数设置为this
  • 第6章:垃圾回收分析与调优
  • 【NVIDIA B200】1.alltoall_perf 单机性能深度分析:基于 alltoall_perf 测试数据
  • 从卡顿到丝滑:3 个实战场景教你搞定代码性能优化
  • DeepSeek、GPT-5都在卷的“快慢脑”,腾讯中科院给出了更优解:还是多模态的!
  • 什么是科技成果鉴定测试?成果鉴定测试报告带给企业什么好处?
  • c语言链表:从入门到精通
  • 深度学习篇---SGD+Momentum优化器
  • wpf之Border
  • 嵌入式 - 硬件:51单片机(2)
  • 08、Linux 安全组开放端口
  • sed——Stream Editor流编辑器
  • 软件测试中的Bug知识总结
  • 81-dify案例分享-零代码用 Dify 使用梦 AI 3.0 多模态模型,免费生成影视级视频
  • 光伏设计方案怎么对比?360°展示规避空间问题
  • Bug 排查日记:从入门到精通
  • 微服务多级缓存:从问题到实战(小白也能看懂的亿级流量方案)
  • MP4视频太大如何压缩?分享6种简单便捷的压缩小技巧
  • 微服务的编程测评系统20-虚拟机-nginx-部署