一、绪
上篇博客和大家分享了ffmpeg的编译流程以及在Android Studio中集成。最近由于对ffmpeg的涉猎进展较慢,但是为了保持持续的狂暴之心,还是不能停止博客的更新。所以今天和大家分享一篇关于设计模式的内容。想必有些朋友看到设计模式几字就有点精神错乱,四肢麻木。哈哈,开个玩笑。我不会以单纯描述设计模式来表达,这样的博客随便一搜很多。既然要说设计模式,毕竟缺少不了实战的结合。
二、介绍
设计模式所带来的效益是显而易见的,23种设计模式体现了7种思想原则的守恒。大家最常用也最常听说的 单例模式、原型模式、工厂模式、观察者模式、建造者模式等等,同样很多模式在Android源码或者优秀的第三方开源库中体验的淋漓尽致。例如图片加载库,Glide,ImageLoader等等都以getInstance的方式使用了单例模式(双重锁检查机制),Android源码中AlertDialog使用build体现的建造者模式,Intent提供的clone原型模式,3.0后的属性动画插值器所体现的策略模式等等。本篇博客和大家分享一下状态模式的定义以及实战的使用。
三、状态模式的定义
状态模式包含了三种定义:
(1)控制器
(2)抽象状态或状态接口
(3)具体状态
怎么理解三者之间的关系呢?看下面展示图:
上图中,Context也就是控制器,即使用环境。State即为抽象状态或状态接口,Concrete State A,B即为具体的状态实现,即状态的具体行为。三者的关系显而易见,在Context中提供setState以注入的方式来改变不同的状态,体现不同状态下的不同行为。
四、简例
生活处处有设计模式。拿生活中的电视遥控器例子来说,在电视开机状态下,遥控器可以控制音量,频道切换等等,关机状态下,对于电视的任何操作都不能进行。
此时,遥控器就对应于Context,State对应于电视的状态,具体状态对应于电视的开机、关机:
代码描述如下:
(1)控制器接口,定义了两种状态的控制。
(2)具体控制器实现,实现状态的切换。
(3)状态接口
(4)开机状态
(5)关机状态
五、实战使用技巧
在我们平时开发的App应用中,肯定缺少不了登录功能。App客户端用户状态一般处于两种状态:
(1)登录状态
(2)注销状态(退出本次登录)
两种状态下对应的App权限是不同的。例如,App中有商品的收藏、分享功能、加入购物车、支付功能等等。
用户未登录状态时,可以进行商品分享操作,但不能对商品进行支付。反之,在用户登录后,即可进行商品收藏,商品下单支付等操作。
一般的做法是,会在每个功能模块下,在业务处理前,例如在收藏功能模块中,首先会对用户的状态进行判断,如果用户处于登录状态,处理收藏逻辑。否则跳转到登录界面,提示用户登录。如果功能模块较少的情况下,还是可以接受。
考虑一种场景:用户状态切换不同的情况下,会有多种不同的状态操作。此时需要在每个地方去做登录状态的判断,显而易见,这种方式非常繁琐。在后面的工作中,如果还有与用户状态相关的操作,都需要去作重复的业务逻辑。
伪代码:
了解到使用一般方式的弊端后,我们可以使用状态模式来解决此问题。经过上面的分析,我们可以得到如下信息:
(1)用户信息
(2)用户状态
(3)状态行为
1.首先定义两种状态,两种状态对应了不同的行为方式:
2.状态行为管理
3.Activity中使用
分析:
首先,定义了两个具体的状态类,并且实现了不用的行为处理方式。在登录状态下,可以进行收藏和支付。在未登录状态下,执行收藏和支付行为时,直接跳转到登录界面。
然后,为了不在Activity直接操作State的行为,避免了Activity和State耦合,引入了LoginContext单例类,以委托的方式通过状态类来管理State的行为和状态。
最后在Activity中通过LoginContext来执行具体操作:
首先默认状态是未登录状态,此时点击收藏和支付将跳转到登录界面。等点击登录后,状态变为登录状态,点击收藏或者支付将会进行具体我逻辑处理。
我们可以发现,整体代码逻辑上变得如此清晰,去掉了重复冗余的判断。
六、小结
从上面的实战中,不难发现。使用了状态模式后,代码逻辑变得清晰很多,减少了不必要的代码耦合。同样也可以发现,状态模式基本可以应用在不同状态下的同一行为的不同处理。减少了if else 或者switch的状态判断以及逻辑耦合。但是也同样增加了类和对象的个数。所以还需要我们在实际运用中根据需求来决策具体的使用方式。以上部分内容参考《Android源码设计模式》。