关于代码编写时「抽象」概念的一点点心得

关于抽象,是面向对象的特性,之前实际写代码的时候,可能注意得不是很好,对于这个点的理解也不是很到位。

但是因为公司项目涉及到了组件化,不同组件之间的通信其实是依赖抽象接口来规范的,或者说是约束的。

而一开始,我在定义抽象接口的时候,就处理得不是很好,偶尔会把具体业务层的实现带到接口定义之中,虽然觉得这样有点不对劲,但是却无法参透。

后来,在 code review 的时候,我的导师针对我的问题跟我聊了聊,在受到点拨之后,我感觉我对此的认知有了些许进步。

说得简单的,就是:

抽象层不应该对外暴露具体的实现参数,即不是面向实现编程,而要面向抽象编程。

因为对于抽象层来说,并不应该关心具体的实现,只需要做到 “定义”,至于业务层具体怎么实现,那是业务的事,在外人看来,只需要根据抽象层对外暴露的对应的接口方法能够实现目的即可。

而且对于抽象层来说,要做到替换业务层的实现,对外是无感知的,但是如果抽象层参杂了业务层的东西,那还怎么做到替换业务层的时候对抽象层不产生影响。

比如我对外定义一个抽象接口 IPageService,里面有个抽象方法 toUserInfoPage(),用于表示跳转到应用的用户信息页。

但是,在具体的实现中,假设有两种情况,一种是用户信息页实际上在首页的一个 tab 项,假设是第 X 个 tab,那跳转到个人信息页此时就对应跳转到首页第 X 个 tab 的逻辑;第二种则是用户信息页是一个二级页面,那此时的逻辑则是跳转到对应的 Activity。

此时,如果抽象层没有定义好,针对第一种情况,则可能会将形参 Int index 也带入到 IPageService#toUserInfoPage() 方法中,从而变成,fun toUserInfoPage(index: Int),用来在实现类 IPageImpl 中通过参数 index 来指定跳转到首页第 X 个 tab(即个人信息页)。

interface IPageService {
	fun toUserInfoPage(index: Int)
}

class PageFirstImpl: IPageService {
	fun toUserInfoPage(index: Int) {
		// use index jump to user info tab
	}
}

这种情况下,其实就是对外暴露了业务层的实现,而且调用的时候必须要指定 index 为 X 才能达到目的。

val pageService = PageFirstImpl()
// should introduce X, and should know index be X
pageService.toUserInfoPage(X)

之后,如果要该成第二种实现,此时参数 index 就相当于摆设了,不会有丝毫用处。

class PageSecondImpl: IPageService {
	fun toUserInfoPage(index: Int) {
		// start UserInfoActivity, index is useless
	}
}

而正确的实现应该是像下面那样,在具体的实现类中直接指定 X 即可,因为外部调用时根本是不需要知道的,只要能够实现跳转到用户信息页即可。

interface IPageService {
	fun toUserInfoPage()
}

class PageFirstImpl: IPageService {
	fun toUserInfoPage() {
		val index = X
		// jump to user info tab via local variable ‘index’
	}
}

再补充一点,即不要本末倒置地先去想到业务层应该怎么实现,再根据实现去定义抽象层的接口方法,这个时候就会被业务层的参数给影响到。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值