2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > Android设计模式详解之观察者模式

Android设计模式详解之观察者模式

时间:2020-04-13 12:39:42

相关推荐

Android设计模式详解之观察者模式

前言

观察者常用于订阅-发布系统,能够将观察者和被观察者进行解耦,降低两者之间的依赖;

定义:定义对象间一种一对多的依赖关系,使得每当一个对象改变状态时,则所有依赖于它的对象都会得到通知并被自动更新。

使用场景:

关联行为场景,需要注意的是,关联行为是可拆分的,而不是组合关系;事件多级触发场景;跨系统的消息交换场景,如消息队列、事件总线的处理机制。

UML类图:

Subject:抽象主题,被观察者的角色,抽象主题角色把所有观察者对象的引用保存到一个集合中,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察对象;ConcreteSubject:具体主题,具体被观察者,该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发出通知;Observer:抽象观察者,该角色是观察者的抽象类,它定义了一个更新接口,使得在得到主题的更改通知时更新自己;ConcreteObserver:具体的观察者,该角色实现抽象观察者角色所定义的更新接口,以便在主题的状态发生变化时更新自己的状态;

实现示例

这里以关注微信公众号进行举例,对于公众号是被观察者,对于微信用户则是观察者,微信用户订阅微信公众号后,公众号发布文章通知到微信用户,典型的发布-订阅模式;下面我们就用观察者模式来实现:

定义抽象观察者,Observer

interface Observer<T> {//定义文章更新方法fun update(t: T)}

定义抽象被观察者,持有所有的观察者,Observable

open class Observable<T> {private val observers = arrayListOf<Observer<T>>()/*** 订阅被观察者*/fun addObserver(observer: Observer<T>) {observers.add(observer)}/*** 解除订阅*/fun removeObserver(observer: Observer<T>) {observers.remove(observer)}/*** 通知所有的观察者*/fun notifyObservers(t: T) {for (observer in observers) {observer.update(t)}}}

具体观察者,微信用户,WXUser

class WXUser(private val name: String) : Observer<String> {override fun update(article: String) {println("$name receive article:$article")}}

微信公众号,具体的被观察者,WXPublicObservable

class WXPublicObservable : Observable<String>() {/*** 更新公众号文章*/fun updateArticle(article: String) {notifyObservers(article)}}

编写测试类以及测试结果

object Test {@JvmStaticfun main(args: Array<String>) {//定义微信用户val user1 = WXUser("user1")val user2 = WXUser("user2")val wxPublicObservable = WXPublicObservable()//订阅公账号wxPublicObservable.addObserver(user1)wxPublicObservable.addObserver(user2)//发布一篇文章wxPublicObservable.updateArticle("互联网行业,迎来寒冬...")println("---------------------------")println("---------------------------")//user1取消订阅wxPublicObservable.removeObserver(user1)wxPublicObservable.updateArticle("疫情何时才能结束...")}}

user1 receive article:互联网行业,迎来寒冬...user2 receive article:互联网行业,迎来寒冬...------------------------------------------------------user2 receive article:疫情何时才能结束...

Android源码中的观察者模式

ListView中的观察者模式;

我们首先看下ListView.setAdapter方法

public void setAdapter(ListAdapter adapter) {//判断是否之前已经注册过观察者,如果注册过先注销,避免多次注册;if (mAdapter != null && mDataSetObserver != null) {mAdapter.unregisterDataSetObserver(mDataSetObserver);}...super.setAdapter(adapter);if (mAdapter != null) {//创建一个数据集观察者进行注册mDataSetObserver = new AdapterDataSetObserver();mAdapter.registerDataSetObserver(mDataSetObserver);...requestLayout();}

我们紧着看下AdapterDataSetObserver

class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver {@Overridepublic void onChanged() {super.onChanged();if (mFastScroll != null) {mFastScroll.onSectionsChanged();}}@Overridepublic void onInvalidated() {super.onInvalidated();if (mFastScroll != null) {mFastScroll.onSectionsChanged();}}}

AdapterDataSetObserver会继承DataSetObserver,我们看下DataSetObserver,典型的一个抽象观察者角色

public abstract class DataSetObserver {public void onChanged() {}public void onInvalidated() {}}

通过上面的ListView.setAdapter方法,就完成了观察者注册工作,我们在看下数据更新时,我们一般会调用notifyDataSetChanged方法

private final DataSetObservable mDataSetObservable = new DataSetObservable();public boolean hasStableIds() {return false;}public void registerDataSetObserver(DataSetObserver observer) {mDataSetObservable.registerObserver(observer);}public void unregisterDataSetObserver(DataSetObserver observer) {mDataSetObservable.unregisterObserver(observer);}public void notifyDataSetChanged() {mDataSetObservable.notifyChanged();}

mDataSetObservable代码如下,显然,调用notifyDataSetChanged方法实际上就是让被观察者去通知观察者数据发生了变化;

public class DataSetObservable extends Observable<DataSetObserver> {public void notifyChanged() {synchronized(mObservers) {for (int i = mObservers.size() - 1; i >= 0; i--) {mObservers.get(i).onChanged();}}}public void notifyInvalidated() {synchronized (mObservers) {for (int i = mObservers.size() - 1; i >= 0; i--) {mObservers.get(i).onInvalidated();}}}}

我们在回头看下AdapterDataSetObserver的onChanged()方法都做了什么

class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver {@Overridepublic void onChanged() {super.onChanged(); //重点看下 super.onChanged()方法if (mFastScroll != null) {mFastScroll.onSectionsChanged();}}@Overridepublic void onInvalidated() {super.onInvalidated();if (mFastScroll != null) {mFastScroll.onSectionsChanged();}}}

super.onChanged()对应AdapterDataSetObserver.onChanged()方法

class AdapterDataSetObserver extends DataSetObserver {@Overridepublic void onChanged() {mDataChanged = true;mOldItemCount = mItemCount;mItemCount = getAdapter().getCount();if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null&& mOldItemCount == 0 && mItemCount > 0) {AdapterView.this.onRestoreInstanceState(mInstanceState);mInstanceState = null;} else {rememberSyncState();}checkFocus();//最终会通过 requestLayout()完成listview所有数据更新requestLayout();}

小结:Listview数据更新是典型的观察者设计模式,在setAdapter方法里完成了观察者的注册工作,当调用notifyDataSetChanged方法的时候最终会通过requestLayout()完成所有数据更新!

总结

优点:

观察者和被观察者之间是抽象耦合,应对业务变化;增强系统灵活性、可扩展性;

缺点:

程序中包括一个被观察者,多个观察者对象,消息通知是遍历执行的,一个观察者卡顿,会影响整体的执行效率,这时候可以考虑采用异步的方式。

结语

如果以上文章对您有一点点帮助,希望您不要吝啬的点个赞加个关注,您每一次小小的举动都是我坚持写作的不懈动力!ღ( ´・ᴗ・` )

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。