最简单的观察者模式实现

来源:互联网 发布:java中的标识符 编辑:程序博客网 时间:2024/05/19 03:42

前言:1.在做项目的过程中很多地方都有用到观察者模式,不过都是系统封装好的,或者是别人的框架,比如系统的广播,网上比较流行的EventBus事件总线其内部原理都是对观察者模式的具体实现;还有Android中的大部分名为notifyDataSetChange方法的调用,其内部实现也是观察者模式,没错,listView和GridView常用的适配器中就有此方法,我们常用来提醒listview和gridview刷新界面显示。

一:系统的简单实现:

其实Android系统中最简单的观察者模式的实现是Observable(抽象类),Observer(接口),代码都比较少如下:

Observable(抽象类——被观察者):内部维护了一个装有所有观察它的观察者对象集合(list),当本身内容变化时,就遍历集合调用每个观察者对象的update方法

public class Observable {    List<Observer> observers = new ArrayList<Observer>();//维护的所有观察者对象的集合,每个Observer都是一个观察者    boolean changed = false;    public Observable() {//空构造    }    public void addObserver(Observer observer) {      //   将一个观察者Observer添加到观察者集合(list)中        if (observer == null) {            throw new NullPointerException("observer == null");        }        synchronized (this) {            if (!observers.contains(observer))                observers.add(observer);        }    }     protected void clearChanged() {        changed = false;    }    public int countObservers() {        return observers.size();    }    public synchronized void deleteObserver(Observer observer) {   //   将一个观察者Observer从观察者集合(list)中移除        observers.remove(observer);    }    public synchronized void deleteObservers() {//   移除所有的观察者        observers.clear();    }    public boolean hasChanged() {        return changed;    }    public void notifyObservers() {//提现所有观察者自身发生了变化,转调用带参数的同名函数notifyObservers        notifyObservers(null);    }    @SuppressWarnings("unchecked")    public void notifyObservers(Object data) {    //真正的遍历集合提醒每一个观察者自身发生了变化,并传递参数,调用每个观察者的update方法        int size = 0;        Observer[] arrays = null;        synchronized (this) {            if (hasChanged()) {                clearChanged();                size = observers.size();                arrays = new Observer[size];                observers.toArray(arrays);            }        }        if (arrays != null) {            for (Observer observer : arrays) {                observer.update(this, data);            }        }    }    protected void setChanged() {        changed = true;    }}

Observer(接口——观察者) 实现了该接口的子类调用被观察者Observable的addObserver方法,将自身加入到被观察者维护的所有观察者集合中(list),注销(反注册)的时候调用被观察者Observable的deleteObserver方法将自身从list集合中移除。

public interface Observer { //该接口中只有一个方法    void update(Observable observable, Object data);}

二 :系统中的观察者模式 

Android的四大组件内容提供者,广播,列表展示中常用的BaseAdapter,不都是观察者模式的不同实现吗,原理大致相同,Api的都有类似性,比如register方法对应addObserver方法,unregister对应deleteObserver方法,一般都和Activtiy的生命周期绑定调用;

三:自己写个小Demo     写一个更简单的MyObservable(被观察者),MyObserver(观察者)

Myobservable  (抽象类——被观察者)
public abstract class MyObservable {    private static MyObservable mMyObservable;    private ArrayList<MyObserver> mObservaleList;    private MyObservable() {        mObservaleList = new ArrayList<MyObserver>();    }//  做成单例模式    public final static MyObservable newInstance() {        if (mMyObservable == null) {            mMyObservable = new MyObservable();        }        return mMyObservable;    }    //  注册    public void registerObserver(MyObserver observer) {        if (!mObservaleList.contains(observer)) {//如果没有注册过            mObservaleList.add(observer);        }    }    //  反注册    public void unRegisterObserver(MyObserver observer) {        if (mObservaleList.contains(observer))            mObservaleList.remove(observer);    }    public void notifyDataSetChange(Object data) {        if (mObservaleList != null) {            for (MyObserver observer : mObservaleList) {                observer.update(this, data);            }        }    }}
MyObserver  (接口——观察者)
public interface MyObserver {    void update(MyObservable myObservable,Object data);}

四:结合fragment的具体应用:

先看下效果:

MainActivity
public class MainActivity extends AppCompatActivity implements MyObserver {    private MyObservable mMyObservable;    private TextView mReceiveText;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mReceiveText = (TextView) findViewById(R.id.btn_receiver);        Button btn_next = (Button) findViewById(R.id.btn_next);        btn_next.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                Intent intent = new Intent(MainActivity.this, FragmentActivity.class);                startActivity(intent);            }        });        mMyObservable = MyObservable.newInstance();//被观察者对象        mMyObservable.registerObserver(this);//观察者注册    }    @Override    public void update(MyObservable myObservable, Object data) {        Toast.makeText(this,"MainActivity被提醒了",Toast.LENGTH_SHORT).show();        mReceiveText.setText("我已接收到提醒了,收到内容为:"+(String)data.toString());    }    @Override    protected void onDestroy() {        super.onDestroy();        mMyObservable.unRegisterObserver(this);//观察者移除观察    }}

FragmentActivity

public class FragmentActivity extends android.support.v4.app.FragmentActivity implements FragmentDemo.ClickListener {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.fragment);    }    @Override    public void click(String str) {        Toast.makeText(this, "fragment中输入不为空时我在Activity中接收到了内容:"+str, Toast.LENGTH_SHORT).show();    }}

FragmentDemo(自定义fragment)
public class FragmentDemo extends Fragment {    private ClickListener mClickListener;    private EditText et_input;    public interface ClickListener {        void click(String str);    }    @Override    public void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        if (getActivity() instanceof ClickListener) {            mClickListener = (ClickListener) getActivity();        }        Log.i("fragmentDemo-Life cycle", "onCreate");    }    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        Log.i("fragmentDemo-Life cycle", "onCreateView");        View view = inflater.inflate(R.layout.fragmentdemo, container, false);        Button btn_notify = (Button) view.findViewById(R.id.btn_notify);        et_input = (EditText) view.findViewById(R.id.et_input);        Button btn_click = (Button) view.findViewById(R.id.btn_click);/** *fragment与宿主之间的交互,比如我们点击fragment中的控件时,我们要将一些操作,或则数据回传到宿主Activity做一些执行,这里一般有2中方法; * 1.在Activity中直接写一个方法method,在fragment中直接调用getActivity(),方法拿到Activity实例直接调用Activity中的method方法。 * 2.在fragment中写一个接口,接口里有一个方法method,让他的宿主activity去实现接口并重写method方法 * 当然这2种方法哪种较好呢,当然是第二种了,熟悉fragment的同学都知道,fragment出现的一个原因就是可以复用,如果我们用第一种方法写的话,我们直接在 * fragment中调用getActiviy(),在调用method方法,那如果我们在ActivityA,ActivityB,ActivityC中都调用用到了fragment,那我们能保证每个Activity中都有 * method方法吗,这样还得做一个fiagment.getActivity() instanceof 目标Activity ;这样写不解耦,不复用; */        btn_click.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                String str = et_input.getText().toString();                if (!TextUtils.isEmpty(str)) {                    if (mClickListener != null)                        mClickListener.click(str);                }            }        });        btn_notify.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                String str = et_input.getText().toString();                if (!TextUtils.isEmpty(str)) {                    MyObservable.newInstance().notifyDataSetChange(str);                }            }        }); return view;    }}


五:个人总结:

个人觉得观察者模式的核心同我们简单的接口调用一本样,只是我们常用的接口调用的时候常用setXXXXX方法设置一个监听,当监听到的时候我们给设置了监听的一个对象一个回调方法,而观察者模式只是将多个监听对象放到了一个集合里,当变化时给所有的监听对象都回调一下

Demo源码如下:http://download.csdn.net/detail/themelove/9425973


1 0
原创粉丝点击