澳门皇冠官网app观看者情势那种公布-订阅的花样大家可以拿微信公众号来比喻,观看者方式(Observer

HTTP DNS 解析性能监控

有那样一个风貌,大家的行使接入了 HTTP DNS,接管了几许接口请求的 DNS
解析。现在某些有统计报告接口,在少数地方,必要 DNS
解析的有些新闻,比如解析到的 IP,解析耗时,解析拔取的域名服务器地址

俺们可以动用阅览者来化解这么些标题

创立一个监控器,内置观察者队列,并提供格局来足够、删除观看者

当 DNS
每一遍发起一回解析,把数据计算后,交给监控器。然后监控公告所有观看者拿多少

概念目标类 DnsMonitor

public class DnsMonitor {

    private final List<MonitorWatcher> mWatcherList;

    public DnsMonitor() {
        mWatcherList = new CopyOnWriteArrayList<>();
    }

    @Override
    public void onParseResult(ResolveData data) {
        if (data == null || TextUtils.isEmpty(data.host)) {
            return;
        }

        // 通知观察者们,有解析数据了
        for (MonitorWatcher watcher : mWatcherList) {
            watcher.notifyResolveData(data);
        }
    }

    /**
     * 注册监视者
     */
    public void registerWatcher(MonitorWatcher watcher) {
        mWatcherList.add(watcher);
    }

    /**
     * 注销监视者
     */
    public void unregisterWatcher(MonitorWatcher watcher) {
        mWatcherList.remove(watcher);
    }
}

概念阅览者

public interface MonitorWatcher {
    /**
     * 通知获取到的解析数据
     */
    void notifyResolveData(ResolveData data);
}

然后,大家的有所 DNS 解析器,在分析到结果后,调用的 onParseResult
把多少暴发去

可以把 Monitor
做成单例,或者放到单例内,那样就能够整个进度都能够访问。所有的观看者们,只需求贯彻
Monitor沃特cher,然后等着数量布告过来

事实上那么些职能还有众多细节,比如怎样幸免唤醒观望者不打断,还有哪些让具有解析器使用同一个监视器。因为和那些情势无关,就不列出来了

优点

解除耦合,让耦合的双方都信赖于肤浅,从而使得个别的变换都不会潜移默化另一面的转换。

定义

观看者形式(Observer
Pattern):定义对象时期的一种一对多保护关系,使得每当一个目标处境暴发改变时,其相关着重对象皆获得关照并被自动更新

切切实实世界的形式

譬如说一些用户订阅了周刊,每一遍周刊发表的时候都会送到用户手上

诸如高考的时候,发送广播布告考试完结,考生都要停笔,教师要求收卷

譬如打仗的时候,指挥官发命令,战场上客车兵跟军命令决定进攻、撤退、驻守

有这几序列型

  • 发布-订阅情势
  • 模型-视图形式
  • 源-监听方式
  • 从属者情势

观看者方式结构图

澳门皇冠官网app 1

  • Subject:抽象宗旨(抽象被观看者),抽象大旨角色把具备观看者对象保存在一个汇集里,每个宗旨都足以有擅自数量的观看者,抽象大旨提供一个接口,可以伸张和删除观看者对象。
  • ConcreteSubject:具体大旨(具体被观看者),该角色将有关意况存入具体观望者对象,在实际宗旨的中间景色发生变更时,给所有注册过的观察者发送通告。
  • Observer:抽象寓目者,是观望者者的抽象类,它定义了一个更新接口,使得在得到宗旨更改通知时更新自己。
  • ConcrereObserver:具体观望者,是落到实处抽象观看者定义的更新接口,以便在取得宗旨更改文告时更新自己的气象。

ContentObserver

有诸如此类一个必要,大家想要知道数据库某个数据的变更,有一种结果方法,那就是开个工作线程,去轮询访问。那样的做法会导致资源多量消耗

Android 提供的一种方法,称为内容观看者,可以监听数据库变化后会通告出来

比如说大家要监听屏幕亮度的更动,并且做一些政工。显示屏亮度变化的数量在系统数据库里,我们可以因此ContentObserver 很自在地取出

显示器亮度对应的 Uri 可以这么得到

Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS)

始建观望者

    private static class ScreenBrightnessObserver extends ContentObserver {

        ScreenBrightnessObserver(@NonNull Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);

            // 亮度发生变化了,可以查询最新的亮度,然后做相应的业务

        }
    }

接下来在页面启动的利用登记

mScreenBrightnessObserver = new ScreenBrightnessObserver(new Handler());
getContentResolver().registerContentObserver(Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS), true, mScreenBrightnessObserver);

在页面销毁的时候注销

getContentResolver().unregisterContentObserver(mScreenBrightnessObserver);

缺点

在应用观看者情势时索要考虑一下开发功用和运作作用的标题,程序中概括一个被寓目者、多个观看者,开发、调试等内容会比较复杂,而且在Java中音讯的关照一般是各样执行,那么一个寓目者卡顿,会影响全体的举办作用,在那种景观下,一般会选用异步落成。

EventBus

伊芙ntBus 也是观看者形式的一种完成

借使大家有三个目的,多少个观察者,如若每个目的都去管理观看者列表的话,维护起来很吓人

之所以那边又抽象出一个层次,可以掌握为新闻中央,或者信息总线,内部维护着观看者的列表,目的发出多少变化交给那些音信中央举行新闻的分发和调度

澳门皇冠官网app 2

观看者形式-伊夫ntBus.png

伊芙ntBus
提供了一个不行强劲音讯总线,目标暴发变化的时候,把要通报的新闻封装成一个个音讯。把信息公告给订阅该音信的观看者们

可以用 伊芙ntBus
在做模块间的通信。把要通报的多少变动封装成事件抛出去。通讯的模块没有耦合,发送者不须要通晓有啥接收者。伊芙ntBus
会布告到位

实际观察者(ConcrereObserver)

微信用户是观望者,里面完成了创新的法子:

public class WeixinUser implements Observer {
    // 微信用户名
    private String name;
    public WeixinUser(String name) {
        this.name = name;
    }
    @Override
    public void update(String message) {
        System.out.println(name + "-" + message);
    }


}

使用实例

3.采纳寓目者格局的场地和优缺点

简单易行设计

目标

被考察的目的,内置抽象寓目者集合,定义扩展、删除、文告抽象寓目者的方法。目的类可以是架空的也可以是切实的。若是有实际的肤浅业务要兑现,仍可以分出目的子类

虚幻观望者

声称了更新数据的措施,由目的调用

切实观看者

心想事成了抽象寓目者的更新数据的方法

如若急需目的的一些意况或者数额状态,可能还保持着对目的的引用

澳门皇冠官网app 3

观看者格局-类图.png

可以动用在一对多的通讯上。同时,目标和阅览者没有太强的依靠和涉及,扩充或者缩减观看者,不会对目的导致影响

接纳意况

  • 事关行为现象,必要小心的是,关联行为是可拆分的,而不是“组合”关系。
  • 事件多级触发场景。
  • 跨系统的新闻沟通场景,如信息队列、事件总线的处理体制。

2.观望者格局简单落成

观看者情势这种公布-订阅的形式大家得以拿微信公众号来比喻,借使微信用户就是观察者,微信公众号是被观望者,有八个的微信用户关怀了程序猿那么些公众号,当这些群众号更新时就会通报那几个订阅的微信用户。好了俺们来探视用代码怎么样贯彻:

定义

观察者方式(又被称呼发布-订阅(Publish/Subscribe)形式,属于行为型方式的一种,它定义了一种一对多的依靠关系,让七个观看者对象同时监听某一个主题对象。那一个大旨对象在情景变化时,会打招呼所有的观察者对象,使她们力所能及自动更新自己。

切实被观看者(ConcreteSubject)

微信公众号是现实性宗旨(具体被阅览者),里面储存了订阅该群众号的微信用户,并落实了抽象主题中的方法:

public class SubscriptionSubject implements Subject {
    //储存订阅公众号的微信用户
    private List<Observer> weixinUserlist = new ArrayList<Observer>();

    @Override
    public void attach(Observer observer) {
        weixinUserlist.add(observer);
    }

    @Override
    public void detach(Observer observer) {
        weixinUserlist.remove(observer);
    }

    @Override
    public void notify(String message) {
        for (Observer observer : weixinUserlist) {
            observer.update(message);
        }
    }
}

1.寓目者格局格局简介

4.Android中的观望者方式

android源码中也有不少应用了观望者情势,比如OnClickListener、ContentObserver、android.database.Observable等;还有组件通信库RxJava、RxAndroid、伊芙ntBus;在此地将拿我们最常用的Adapter的notifyDataSetChanged()方法来比喻:
当我们用ListView的时候,数据爆发变化的时候大家都会调用Adapter的notifyDataSetChanged()方法,那个艺术定义在BaseAdaper中,大家来看看BaseAdaper的一些源码:

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {

    //数据集观察者
    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();
    }

很肯定BaseAdapter用的是观看者情势,BaseAdapter是实际被观看者,接下去看看mDataSetObservable.notifyChanged():

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

咱俩看到了mObservers,那就是观看者的联谊,那一个观看者是在ListView通过setAdaper()设置Adaper时暴发的:

@Override
    public void setAdapter(ListAdapter adapter) {
        if (mAdapter != null && mDataSetObserver != null) {
            mAdapter.unregisterDataSetObserver(mDataSetObserver);
        }
        ...
        super.setAdapter(adapter);

        if (mAdapter != null) {
            mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
            mOldItemCount = mItemCount;
            mItemCount = mAdapter.getCount();
            checkFocus();
            //创建数据观察者
            mDataSetObserver = new AdapterDataSetObserver();
            //注册观察者
            mAdapter.registerDataSetObserver(mDataSetObserver);

            ...
        }

接下去看看观望者AdapterDataSetObserver中拍卖了何等:

class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver {
        @Override
        public void onChanged() {
            super.onChanged();
            if (mFastScroller != null) {
                mFastScroller.onSectionsChanged();
            }
        }

        @Override
        public void onInvalidated() {
            super.onInvalidated();
            if (mFastScroller != null) {
                mFastScroller.onSectionsChanged();
            }
        }
    }

从上边的代码看不出什么,再看看AdapterDataSetObserver的父类艾达pterView的AdapterDataSetObserver:

class AdapterDataSetObserver extends DataSetObserver {
        private Parcelable mInstanceState = null;
        @Override
        public 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();
        }

        ...

        public void clearSavedState() {
            mInstanceState = null;
        }
    }

大家看来在onChanged()方法中调用了requestLayout()方法来重新展开布局。好了,看到那里我们都掌握了,当ListView的数据暴发变化时,大家调用Adapter的notifyDataSetChanged()方法,那几个方法又会调用观看者们(AdapterDataSetObserver)的onChanged()方法,onChanged()方法又会调用requestLayout()方法来再次开展布局。

客户端调用

public class Client {
    public static void main(String[] args) {
        SubscriptionSubject mSubscriptionSubject=new SubscriptionSubject();
        //创建微信用户
        WeixinUser user1=new WeixinUser("杨影枫");
        WeixinUser user2=new WeixinUser("月眉儿");
        WeixinUser user3=new WeixinUser("紫轩");
        //订阅公众号
        mSubscriptionSubject.attach(user1);
        mSubscriptionSubject.attach(user2);
        mSubscriptionSubject.attach(user3);
        //公众号更新发出消息给订阅的微信用户
        mSubscriptionSubject.notify("刘望舒的专栏更新了");
    }
}

结果

杨影枫-刘望舒的专栏更新了
月眉儿-刘望舒的专栏更新了
紫轩-刘望舒的专栏更新了

空泛观看者(Observer)

中间定义了一个翻新的不二法门:

public interface Observer {
    public void update(String message);
}

空洞被观望者(Subject)

空泛主旨,提供了attach、detach、notify多少个点子:

public interface Subject {
    /**
     * 增加订阅者
     * @param observer
     */
    public void attach(Observer observer);
    /**
     * 删除订阅者
     * @param observer
     */
    public void detach(Observer observer);
    /**
     * 通知订阅者更新消息
     */
    public void notify(String message);
}

相关文章