啧啧额,此时发生角色更改,改动的内容就非常小了:
- 修改判断逻辑 → 只在diffRole()方法中发生改动
- 增加角色 → 继承Role写一个角色子类,修改diffRole()方法
- 删除角色 → 直接把角色子类干掉,修改diffRole()方法
妙啊,当时硬是要吹毛求疵的话,也有副作用,就是写多了几个类,23333。
另外还有一点要注意,设计模式不能强行硬套,还要看具体场景,比如这里,因为业务逻辑比较固定,可以这样抽,但是有些业务逻辑经常变动或者角色间逻辑差异过大的,这种玩法就不是很适合了,可能还需要进一步的抽象。
日常开发应用示例二
App里有很多列表页,布局都是 RefreshLayout套一个Recyclerview,然后逻辑都是这样的:
- 数据初始化 (赋初值,解析各种传参,自定义Adapter初始化)
- UI初始化 (参数异常校验错误显示错误UI、RefreshLayout设置上拉刷新和下拉刷新逻辑、RecyclerView设置)
- 请求接口,更新UI(正常状态、异常状态)
没写一个列表页,都要重复一遍,太蠢了,一种解决方式是利用AndroidStudio模板来自动生成。
也可以像笔者一样利用:抽象
+ 泛型
+ 多态
+ 回调
来简化偷懒,核心还是 抽取变化
- 视图 → 列表可能显示不同的布局 → 由Adapter进行控制 → 关联不同的Bean
- 数据 → 列表可能显示不同的数据 → 由请求进行控制 → 关联不同的Request和Response → Response中包含一个Bean的列表,变化的是这个Bean
不难抽出三个变化的类:
- Bean → 与Adapter数据绑定,与Response里的list绑定
- Request → 不同列表请求接口和参数不一样
- Response → 不同列表请求接口响应结果不一样
可以定义成泛型,示例如下:
abstract class DefaultPrlRecFragment<D, Q : Serializable, S : Serializable> : BaseFragment() { abstract val mAdapter: BaseQuickAdapter<D, BaseViewHolder>? // 适配器 abstract val mReq: Q // 请求 abstract val mObservable: Observable<Response<Bean<S>>> // 接口 protected var mData = ArrayList<D>() // 数据 }
子类实现时,传入对应的类型即可,接着到逻辑抽象,先是数据处理这块:
// 读取各种传入数据或进行一些准备,返回true代表正常加载、false表示出现异常 abstract fun prepareData(bundle: Bundle?): Boolean override fun initData(bundle: Bundle?) { if (prepareData(bundle)) { // 正常显示 } else { // 显示异常页面 } } // 发起请求前的一些准备操作 abstract fun beforeRequest() // 加载请求 protected fun loadRequest(isRefresh: Boolean = false) { // 请求处理 } // 请求响应内容解析,提取数据 abstract fun parseData(s: S): DataEntity? // 解析后的数据类 inner class DataEntity( var list: ArrayList<D>?, var allRows: Int, // 总记录数 var pageNum: Int // 总条数 )
再接着是视图,把交互都抽到一个接口中,然后在具体的业务逻辑回调:
private var mListener: InteractiveListener? = null // 交互接口 interface InteractiveListener { fun listEmptyCallback() // 列表空 fun listNormalCallback() // 列表正常显示 fun listItemClickCallback(position: Int) // 列表点击 fun listItemLongClickCallback(view: View, position: Int) // 列表长按 fun onRefreshCallback() // 刷新列表 fun onLoadMoreCallback() // 加载更多 } // 抽象类(提供默认实现,不用重写全部方法) abstract class SimpleInteractiveListener : InteractiveListener { override fun listEmptyCallback() {} override fun listNormalCallback() {} override fun listItemClickCallback(position: Int) {} override fun listItemLongClickCallback(view: View, position: Int) {} override fun onRefreshCallback() {} override fun onLoadMoreCallback() {} } // 添加交互接口 fun addInteractiveListener(listener: InteractiveListener) { this.mListener = listener }
调用示例如下:
网络异常,图片无法展示
|
Fragment写完,接着就到怎么去用它了,继承这个类,传入三个数据类型,重写抽象成员和方法:
网络异常,图片无法展示
|
接着就是 填字游戏 了,示例如下:
网络异常,图片无法展示
|
只需三步,即可实现一个带分页功能的Fragment,又可以偷懒摸鱼了,美滋滋~
0x2、核心总结图
上述两个例子跟笔者做所业务有较强关联,应该很难直接搬运,不过借鉴应该是可以的。当然,笔者勉强算初窥门径,肯定有更好的实现方式,算是抛砖引玉,指出学习设计模式的重要性吧。接着总结一波之前的章节(面试速成必背),具体详细内容可移步至:《把书读薄 | 设计模式之美》 阅读学习,感谢~
概念与OOP
网络异常,图片无法展示
|
设计原则
网络异常,图片无法展示
|
设计模式
网络异常,图片无法展示
|