日常开发应用示例一
拿到新的业务需求,不再是直接无脑拆分输出排期,复制粘贴改改代码,而是考虑更多:后续可能有哪些扩展、重复业务能否抽象复用等。举两个例子:
网络异常,图片无法展示
|
1、App里有不同的角色:二级代理、二级负责人、三级代理、三级负责人,然后一个列表页,不同的角色有不同的交互
如果是你用代码实现,你会怎么做?以前的我可能会这样做,把所有逻辑业务都塞到Fragment,一堆if-else
class UserInfoFragment: Fragment() { // 加载Fragment fun loading() { if(isLeader) { if (isSecond) { // 二级负责人 } else { // 三级负责人 } } else { if (isSecond) { // 二级代理 } else { // 三级代理 } } } // 添加客户 fun addCustomer() { if(isLeader) { if (isSecond) { // 二级负责人 } else { // 三级负责人 } } else { if (isSecond) { // 二级代理 } else { // 三级代理 } } } // 还有下面这些,也是如法炮制 // 搜索 // 选择代理项目 // 筛选 // 排序 // tab切换 }
写if-else写到想哭,如果再来一类角色,又得套一层if-else,改动量巨大,每个方法都要改。
你可能会说,可以简化判断,定义一个常量属性/枚举来标记一种角色,开头走下判断条件,区分出角色,就不用每次都if-else了:
class UserInfoFragment: Fragment() { var role = 0 // 1二级代理人、2二级负责人、3三级代理、4三级负责人 fun init() { if(isLeader) { if (isSecond) { role = 2 } else { role = 4 } } else { if (isSecond) { role = 1 } else { role = 3 } } } // 加载Fragment fun loading() { when(role) { 1 -> 二级代理 2 -> 二级负责人 3 -> 三级代理 4 -> 三级负责人 } }
实际上,还是逃避不了判断,当角色发生改变,依旧要动很多代码,怎么写才能保持可扩展性呢?
抽象 + 多态 + 策略模式
可以把 业务逻辑抽象成一个对象,不同的角色进入这个页面,尽管表现不同,但是执行的业务逻辑是一样的,抽象出一个行为接口:
interface IOperate { fun loading(container: Int) fun addCustomer() fun search(select: SelectItem? = null) fun selectAgentProject(select: SelectItem? = null) fun filter(height: Int, y: Int, select: SelectItem? = null, after: (() -> Unit)? = null) fun order(height: Int, y: Int, after: (() -> Unit)? = null) fun switchTap(pos: Int) }
接着定义一个 抽象角色类 来实现这个接口,原则是这样的:
- 不同角色,相同的逻辑在此重写,相同包括全部相同和部分相同。部分相同指的是部分代码逻辑相同,比如埋点,执行这个逻辑表现不同,但埋点是相同的。子类重写方法,调下super.xxx()复用相同代码,然后重写不同逻辑。
- 完全不同的逻辑,就不在父类中实现,而是交给具体的子类实现
abstract class Role(protected var mFragment: BaseFragment) : IOperate { abstract var type: String // 描述字段,便于区分而已,没用 //... override fun addCustomer() { if (ClickFastUtils.isFastClick()) return mFragment.go(AddCustomerFragment::class.java) umAddClick.um(mFragment.context) } override fun filter(height: Int, y: Int, select: SelectItem?, after: (() -> Unit)?) { umScreenClick.um(mFragment.context) } //... }
然后是 具体角色类,示例如下:
class SecondAgentRole(fg: BaseFragment) : Role(fg) { override var type = "二级代理/经纪人" override fun loading(container: Int) { mFragment.childReplace(SecondAgentListFragment.newInstance(), container) } override fun filter(height: Int, y: Int, select: SelectItem?, after: (() -> Unit)?) { super.filter(height, y, select, after) if (select == null) { shortToast("您当前不在任何代理项目中挂职,无法查看项目客户!") return } after?.invoker() //...其他逻辑 } }
接着就到Fragment了,因为 具体逻辑都分化到对应的角色 里了,所以它非常简单:
class CustomerFragment : BaseFragment() { override fun initData(bundle: Bundle?) { diffRole()?.loading(R.id.fly_content) // 区分用户角色并加载对应Fragment } // 区分用户角色 private fun diffRole(): Role? = when { isLeader && isSecond -> SecondPrincipalRole(this) isLeader && !isSecond -> ThirdPrincipalRole(this) !isLeader && isSecond -> SecondAgentRole(this) !isLeader && !isSecond -> ThirdPrincipalRole(this) else -> null } }