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

架构设计深度解析:策略模式 + 抽象工厂在UI适配中的高级应用

架构设计深度解析:策略模式 + 抽象工厂在UI适配中的高级应用

代码:

// 在 BasePageConfig中 定义了很多抽象方法abstractclassBasePageConfig{companionobject{constvalCOLUM_COUNT_ONE=1constvalCOLUM_COUNT_TWO=2constvalCOLUM_COUNT_THREE=3constvalCOLUM_COUNT_FOUR=4constvalCOLUM_COUNT_FIVE=5constvalCOLUM_COUNT_SIX=6constvalCOLUM_COUNT_EIGHT=8constvalCOLUM_COUNT_TEN=10constvalCOLUM_COUNT_TWENTY=20funget()=if(ViewDelegate.isLandW2560()){LandPageConfig}else{PortPageConfig}}abstractfunrecommendGetGridLayoutManager(context:Context,recyclerView:RecyclerView,bannerWidgetStyle:Int?):GridLayoutManagerabstractfunrecommendSongFolderListMax():IntabstractfunrecommendSongInfoListMax():IntabstractfunmusicHouseGetGridLayoutManager(context:Context,recyclerView:RecyclerView):GridLayoutManager}// 在具体的实现类 LandPageConfig,PortPageConfig中,来实现,会对每个页面,设置具体是多少span/列,写的完整,严谨,很美妙LandPageConfig.kt:objectLandPageConfig:BasePageConfig(){overridefuncreateDecorationConfig():IDecorationConfig{returnLandDecorationConfig}overridefunrecommendGetGridLayoutManager(context:Context,recyclerView:RecyclerView,bannerWidgetStyle:Int?):GridLayoutManager{returnGridLayoutManager(context,COLUM_COUNT_TEN).apply{spanSizeLookup=object:GridLayoutManager.SpanSizeLookup(){overridefungetSpanSize(position:Int):Int{valadapter=recyclerView.adapteras?RecommendAdapterreturnwhen(adapter?.getItemViewType(position)){RecommendData.TYPE_SONG_FOLDER_SUPPLIER_STATION->COLUM_COUNT_TWO RecommendData.TYPE_SONG_ITEM->COLUM_COUNT_FIVE RecommendData.TYPE_BANNER->{if(bannerWidgetStyle==1){COLUM_COUNT_TEN}else{COLUM_COUNT_FIVE}}else->{COLUM_COUNT_TEN}}}}}}overridefunrecommendSongFolderListMax()=COLUM_COUNT_TENoverridefunrecommendSongInfoListMax()=COLUM_COUNT_EIGHToverridefunmusicHouseGetGridLayoutManager(context:Context,recyclerView:RecyclerView):GridLayoutManager{returnGridLayoutManager(context,COLUM_COUNT_TEN).apply{spanSizeLookup=object:GridLayoutManager.SpanSizeLookup(){overridefungetSpanSize(position:Int):Int{valadapter=recyclerView.adapteras?MusicHouseAdapterreturnwhen(adapter?.data?.get(position)?.itemType){MusicHouseItem.TYPE_TITLE_MORE->COLUM_COUNT_TEN MusicHouseItem.TYPE_NEWEST_SONG_ITEM->COLUM_COUNT_FIVEelse->COLUM_COUNT_TWO}}}}}总结: base中把每个页面,对应一个函数名称,在实现类 LandPageConfig,PortPageConfig中,写需要多少span,也就是占多少列

它属于典型的**“策略模式 + 抽象工厂”**在 UI 适配中的高级应用。

我也觉得这段代码写得很好,好在以下三点:

1. 将“业务逻辑”与“布局参数”彻底解耦

在一般的代码里,我们经常会在 Fragment 里面写大量的if (isLandscape) 5 else 2
而这段代码把**“一共有几列”、“某个 Item 占几格”**这些琐碎的数值,全部抽离到了LandPageConfigPortPageConfig中。

  • 好处: 你的 Activity 或 Fragment 变得极其干净,它只需要调用Config.get().recommendGetGridLayoutManager(),完全不需要关心当前是横屏还是竖屏。

2. 利用 SpanSizeLookup 实现极高的灵活性

LandPageConfig里的这段逻辑:

overridefungetSpanSize(position:Int):Int{returnwhen(adapter?.getItemViewType(position)){TYPE_SONG_ITEM->COLUM_COUNT_FIVE// 歌曲占 5 格(一行俩)else->COLUM_COUNT_TEN// 其他占满 10 格(一行一个)}}

这里的“美感”在于:它把 RecyclerView 的复杂布局转换成了简单的数学题。
通过COLUM_COUNT_TEN(总共10列)作为分母,不同的 Item 可以自由分配:

  • 想一行显示 2 个?那就占 5 格。
  • 想一行显示 5 个?那就占 2 格。
  • 想占满全屏?那就占 10 格。

这种以最小公倍数作为总列数的思想,让 UI 调整变得像拼图一样简单。

3. 强迫症级别的“严谨性”

  • 单例化(Object):LandPageConfig用了object关键字,这意味着这些配置在内存中只有一份,不会重复创建对象,非常省内存。
  • 类型安全:在 Base 类里定义abstract fun,强制子类必须实现。这样如果你以后要加一个“折叠屏配置”,编译器会立刻提醒你:“嘿,你还没给折叠屏设置歌曲列表的最大值呢!”——这避免了低级错误。

核心感悟:配置化思想

你发现的这种“美”,其实是**“配置化”**的思想。

  • Base 层:定义了规则(有哪些页面需要配置?)。
  • 实现层:填入数值(具体这个环境下的列数是多少?)。
  • 调用层:只负责执行。

这种结构不仅写起来爽,后期维护更爽:如果老板说“横屏下推荐位想从 2 列改成 3 列”,只需要去LandPageConfig改一个数字,其他几千行代码动都不用动。


http://www.cnnetsun.cn/news/1765199.html

相关文章:

  • 别再只会用按钮了!教你用Qt给STM32小车写个‘键盘侠’上位机,支持组合键控制
  • baidupankey:智能提取码解析实现97%效率提升
  • Python安装Geopandas全攻略:从依赖库到实战避坑指南
  • 【限时开放】微软Blazor MVP私藏插件仓库(2026.3最新版),含3个未上架调试增强工具——仅限前500名开发者领取
  • Windows USB设备开发终极指南:UsbDk驱动套件完整教程
  • 你的技术文档协作卡在格式上了吗?试试用docx2markdown打通Word和GitHub的任督二脉
  • 如何用VRM-Addon-for-Blender解决3D模型跨平台兼容难题:从格式转换到性能优化的完整指南
  • AI教材生成秘籍:低查重技巧与实用工具分享
  • KMS_VL_ALL_AIO:智能激活解决方案全解析
  • WinSCP高效配置指南:实现Windows与Linux服务器无缝文件传输
  • 3大核心功能实现视频自动化:JianYingApi批量处理解决方案
  • 瑞萨RZT2L开发板实战:CoreMark移植全流程避坑指南(附FSP1.2配置)
  • 聊一聊 C# 中的闭包陷阱:foreach 循环的坑你还记得吗?妆
  • VirtualBox安装失败?别慌!手把手教你解决‘严重错误‘回滚问题(附VC++2019下载)
  • 告别固定菜单!用YOLO-World实现‘看图说话’式物体检测,保姆级环境搭建与实战教程
  • 如何避免精益管理咨询后效果回潮?新益为长效固化方法详解
  • 如何用lunar-javascript快速搞定农历计算?完整指南
  • ICRA 2025叉车顶会论文拆解:不用真实数据,如何实现AGV视觉零样本Sim2Real?
  • RoPE 数学本质
  • MFC对话框开发:如何防止Enter和Esc键意外关闭窗口(附3种实用方案)
  • Gradio Agents MCP Hackathon 2025 — Agent Track 荣誉奖_Honorable Mention--仅需425 行 Python
  • Windows10下PowerDesigner16.5安装与汉化全攻略(附资源下载)
  • 告别云端API!用LM Studio和你的RTX4060Ti免费玩转DeepSeek R1 14B大模型
  • 如何有效测试分布式系统:10个核心方法论深度解析
  • ROS Melodic下UR3机械臂与Robotiq FT300力传感器的Gazebo仿真实战(避坑指南)
  • 自由职业程序员的时间管理:比上班更高效
  • 如何自动化获取Steam游戏Depot清单:Onekey工具完全指南
  • Kandinsky-5.0-I2V-Lite-5s镜像优势:Web界面+自动服务+依赖全内置
  • 3个效率倍增技巧:B站字幕全流程解决方案让内容处理效率提升10倍
  • BLE协议栈架构与核心协议层实战指南