Android环境下手动写出观察者模式(非原生)

来源:互联网 发布:淘宝退款骗局过程 编辑:程序博客网 时间:2024/06/02 05:39

之前有一篇用Java原生条件下写出的观察者模式,现在在Android环境下手写出观察者模式。所谓手写即实现的对象不是Java API本身提供的。开始了,代码如下。

1、首先我们需要创建一个主题接口,以什么为主题呢?嗯,今天就以获胜为主题,获胜奖品是500万RMB。

package com.example.demo10_observer_pattern;/** * Created by fuzhihuang on 2017/7/18. */public interface Subject {    // 注册观察者    void registObserver(Observer o);    // 移除观察者    void removeObserver(Observer o);    // 发生改变通知观察者    void notifyChangeObserver();}
如上,我们给接口自定义了3个方法,分别是注册观察者,移除观察者,然后观察对象发生改变通知观察者。


2、有了主题,下面我们要定义一个观察者接口了,所有观察者都得死,不是,是所有观察者都得继承它。

package com.example.demo10_observer_pattern;/** * Created by fuzhihuang on 2017/7/18. */public interface Observer {    void updata(String msg);}
很简单,对不对,里面就一个方法,数据改变的方法。


3、好了,两个方法都有了,那么我们需要两个类分别实现两个接口,首先第一个类就是主题类当然是实现主题接口:

package com.example.demo10_observer_pattern;import java.util.ArrayList;import java.util.List;/** * Created by fuzhihuang on 2017/7/18. */public class WinSubject implements Subject {    List<Observer> mObservers = new ArrayList<>();    // 中奖信息    String msg = null;    @Override    public void registObserver(Observer o) {        mObservers.add(o);    }    @Override    public void removeObserver(Observer o) {        int index = mObservers.indexOf(o);        if(index >= 0)            mObservers.remove(index);    }    @Override    public void notifyChangeObserver() {        for(Observer o : mObservers)            o.updata(msg);    }    public void setMsg(String msg) {        this.msg = msg;        // 通知改变        notifyChangeObserver();    }}
咱们先来看看里面有些什么,首先定义了一个List集合,这个List集合当然只能装我们的观察者咯。然后我们复写了这3个方法,方法1注册观察者,方法体也很简单,无意是添加观察者;方法2移除观察者,怎么移除呢,我们先取到该观察者在List集合中索引的位置,如果索引大于或者等于0,那么我们就用remove移除掉他即可,当然我们需要知道的就是如果是遍历集合,进行移除会出现一些BUG,出现BUG的原因是移位了,嗯,这么简单的BUG肯定也不需要我多BB了,最主要的是这个地方不会出这个错;复写的第三个方法就是我们遍历此集合,然后发出调用观察对象的updata方法,为什么需要遍历呢?因为我们的观察者远远不止一个,所以得遍历所以一一发出通知。等等复写完3个方法后,我们自己又写了一个方法,setMsg设置一些消息,这个方法什么时候调用呢,谁设置消息谁就调用,谁想让消息发生改变谁就调用,后文在调用此方法的位置会接着讲。


4、我们的第二类肯定就是实现观察者接口的类我么,我们暂且叫它为观察者1吧:

package com.example.demo10_observer_pattern;import android.content.Context;import android.widget.Toast;/** * Created by fuzhihuang on 2017/7/18. */public class Observer1 implements Observer {    Context context;    Subject subject;    public Observer1(Context context, Subject subject) {        this.context = context;        this.subject = subject;        // 创建自身对象时注册观察者        subject.registObserver(this);    }    @Override    public void updata(String msg) {        Toast.makeText(context, "目标发生改变,改变内容为:" + msg, Toast.LENGTH_SHORT).show();    }}
我们看看它做了些什么?有一个构造方法,里面注册了一个观察者,它是怎么注册的呢,通过构造传递过来的主题对象进行注册的,还有这种操作吗?我们分析下第一个方法一共做了些什么,通过构造获得了两个对象,第一个对象就是上下文,第二个对象就是我们的主题接口,主题接口就是用来注册的,注册不是需要传递参数吗?那么我们传自己好了,因为类的本身就是一个observer。然后我们观察第二个方法,这个方法就是重写接口里的方法,方法体仅仅是打印了一句吐司,为什么叫他为Android环境下的观察者呢,因为它可以打印吐司啊。哈哈哈。


最后我们在MainActivity里面点击按钮进行一系列的事件:

package com.example.demo10_observer_pattern;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.TextView;public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        TextView tv = (TextView) findViewById(R.id.tv);        tv.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                WinSubject subject = new WinSubject();                Observer1 observer1 = new Observer1(MainActivity.this, subject);                subject.setMsg("中500万");            }        });    }}
先是找到控件TextView,然后注册点击监听,biubiubiu我一点,它就走了这一个内部类里面的代码,先是new了一个获胜主题的对象,然后再new了一个观察者对象,然后调用了获胜主题对象中setMsg的方法,serMsg方法中有个notifyChangeObserver的方法,然后依次遍历获取每一个观察者,最后调用updata方法。所以屏幕中就出现了:目标发生改变,改变的内容是中500万。

原创粉丝点击