观察者模式

模式定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都能得到通知并被自动更新

场景1:短信订阅某资讯,当资讯有更新时通知订阅者

场景2:微信订阅公众号,当公众号有新消息时会通知订阅者

场景中订阅资讯的人即为观察者,观察者不用时刻关注资讯的变化,当资讯有更新时,会立刻通知订阅资讯的人,即观察者;里面存在一对多的关系,资讯可以被多个人订阅,被观察的事物只有一个而观察事物的人可以有多个

类1:Observer:观察者

类2:Observable:被观察者

类3:News:资讯

示例代码:

定义观察者,观察者中只要接受资讯即可,接受的类型定义为泛型

public interface Observer<T> {
    void receive(T data);
} 

定义被观察者,被观察者提供三个方法,订阅/取消/通知

 

public class Observable <T> {
    private List<Observer<T>> list = new ArrayList<>();
    public void register(Observer<T> observer){
        if(observer == null)
            return;
         synchronized (this){
            if (!list.contains(observer)){
                list.add(observer);
            }
        }
    }
    public void unregister(Observer<T> observer){ list.remove(observer); }
    public void notifyObserver(T t){
        for (Observer<T> observer:list){
            observer.receive(t);
       }
 }
}

 

定义资讯类News,资讯类中放一个内容属性作为测试,一个构造方法以及get/set方法,

public class News{
    private String content;
    public News(String content) {
        this.content= content;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content= content;
    }
}

MainActivity中做测试,当资讯发生变化时Observer是否能接收到通知

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Observer<News> observer1 = new Observer<News>() {
            @Override
            public void receive(News data) {
                Log.i("TAG","观察者1接收到信息:"+data.getContent());
            }
        };
        Observer<News> observer2 = new Observer<News>() {
            @Override
            public void receive(News data) {
                Log.i("TAG","观察者2接收到信息:"+data.getContent());
            }
        };

        Observable<News> observable = new Observable<>();

        observable.register(observer1);
        observable.register(observer2);

        observable.notifyObserver(new News("某路人中奖100w"));

        observable.unregister(observer1);//观察者1取消订阅
        observable.notifyObserver(new News("某路人中奖100w消息是假的"));
 }
}

打印TAG:

I/TAG: 观察者1接收到信息:某路人中奖100w

I/TAG: 观察者2接收到信息:某路人中奖100w

I/TAG: 观察者2接收到信息:某路人中奖100w消息是假的

 

当观察者1取消订阅时,移除数组不再触发接口。

observable对象持有一个集合,observer对象通过register方法传入observable并加入observable持有的集合中;unregister方法把observer对象移除集合;notifyObserver方法通过遍历集合获得集合内的Observer对象,并把外部传入的参数放入接口从而触发;其实就是接口回调

源码中也有很多用到类似的模式,setOnclickListener使用接口回掉,是一对一的使用,而addListener系列使用的是上面的模式,例如EditText的输入监听

        使用addTextChangeListener添加监听 new EditText(this).addTextChangedListener(new TextWatcher() {...})

查看addTextChangeListener方法

 

public void addTextChangedListener(TextWatcher watcher) {
    if (mListeners == null) {
        mListeners = new ArrayList<TextWatcher>();
    }

    mListeners.add(watcher);
}

眼熟,内部同样是加入集合;其它还有很多。

Over!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值