最简单的观察者模式实现

前言: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方法设置一个监听,当监听到的时候我们给设置了监听的 一个 对象一个回调方法,而观察者模式只是将 多个 监听对象放到了一个集合里,当变化时给所有的监听对象都回调一下



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值