观察者模式

来源:互联网 发布:单片机如何烧程序 编辑:程序博客网 时间:2024/06/15 10:31

前言

关于观察者模式,经常提及,其实我们在项目开发过程中也经常用到,但是对于这个 东西一直不是很明朗,今天找了些资料做了个整理。以下是我对观察者模式的理解。

我认为,观察者模式在实际运用中,绝大多数的情况都会牵扯到接口回调的结合使用。其中最明显的例子就是安卓开发中的点击事件。以button为例,当点击动作发生的时候,会立即走到点击事件监听的onClick方法中。这个现象不难理解,那么他是怎么实现的呢?

首先触发者,也就是用户,与被触发者,按钮。这两者之间必然存在着一种即时的关系。什么叫即时?就是你打我一下我立马感觉到疼,因为动作触发的那一刹那,神经与皮肤之间存在这关联,可以立马感知到这个结果。

以上是我结合生活中的实例,举的一个很浅显的例子。如果还不懂的话,可以找个人多打你几次试试。

解析

根据所找到的资料显示,观察者模式是一种一对多的即时关系,以上所举的例子都是一对一,一对一也算是一对多的一种。

那么在这个过程中,需要有两个对象概念,观察者,被观察者;以上的例子其实还不完善,有一个比较经典的例子就是警察抓小偷,首先,警察是观察者,小偷是被观察者,如果小偷要偷东西,那么警察肯定会立马作出反应去抓他。之所以说这个例子比较经典,是因为,在小偷偷东西的一刹那,警察对于偷的动作具有高度敏感性,从而立马去作出反应。因此,这种关系常常作为观察者模式中一种比较经典的案例。

以上说到两个概念,观察者,被观察者【也被称作主体】,通常在代码中为了实现一对多的关系,需要多层封装,也就是最底层用interface来实现,那么这样的观察者被称为抽象观察者,这样的被观察者成为抽象被观察者,或抽象主体。

抽象观察者

public interface BaseObserver {    void update(String info);}

抽象被观察者【抽象主体】

public interface BaseSubject {    //注册行为    void subscribe(BaseObserver observer);    //解注册行为    void unSubscribe(BaseObserver observer);    //通知观察者    void notify2Observer(String info);}

首先看到,如果你要实现观察者模式,也就是警察抓小偷的功能时,需要注意。两者之间首先需要通过注册形成关联,也就是,警察与小偷的身份是怎么形成的。这个方法需要在被观察者中实现,这里的注册功能就是subscribe方法。同时在真正的实践应用中,你还可以进行解绑行为,也就是这里的unSubscribe方法【当然这里不要生搬硬套警察抓小偷】,同时,还有一个触发动作的方法,也就是小偷的偷东西行为,这里就是notify2Observer方法。

那么我们来看具体实现

观察者1

public class Observer1 implements BaseObserver {    private OnGetInfoFromSubjectListener listener;    @Override    public void update(String info) {        if (listener != null) {            listener.onGetInfo(info + "observer1");        }    }    public void setOnGetInfoFromSubjectListener(OnGetInfoFromSubjectListener listener) {        this.listener = listener;    }}

观察者2

public class Observer2 implements BaseObserver {    private OnGetInfoFromSubjectListener listener;    @Override    public void update(String info) {        if (listener != null) {            listener.onGetInfo(info + "observer2");        }    }    public void setOnGetInfoFromSubjectListener(OnGetInfoFromSubjectListener listener) {        this.listener = listener;    }}

注:这里我手动写了一个接口回调用于向外部暴露数据

被观察者【主体】

public abstract class Subject implements BaseSubject {    private ArrayList<BaseObserver> mObserverList = new ArrayList<>();    @Override    public void subscribe(BaseObserver observer) {        mObserverList.add(observer);    }    @Override    public void unSubscribe(BaseObserver observer) {        mObserverList.remove(observer);    }    @Override    public void notify2Observer(String info) {        for (BaseObserver observer : mObserverList) {            observer.update(info);        }    }}

最终对外部暴露的被观察者

public class RealSubject extends Subject {    private String mInfo = "I am a subject and was subscribed by ~ ";    public void sendInfo2Observer() {        notify2Observer(mInfo);    }}

之前已经讲过,首先要实现这些功能,第一部要进行注册,然后再去更新数据进行通知。为了让这个过程更具体,我写了一个界面。

第一步点击subscribe,第二步点击notify,即可看到数据立马显示在屏幕上。

那么首页的代码

public class MainActivity extends AppCompatActivity implements View.OnClickListener {    private TextView mTvInfoFromObserver1;    private TextView mTvInfoFromObserver2;    private Button mBtnSubscribe;    private Button mBtnNotify;    private RealSubject mRealSubject;    private Observer1 mObserver1;    private Observer2 mObserver2;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_home);        initView();        initAction();        initData();    }    private void initData() {        if (mRealSubject == null) {            mRealSubject = new RealSubject();        }        if (mObserver1 == null) {            mObserver1 = new Observer1();            mObserver1.setOnGetInfoFromSubjectListener(new OnGetInfoFromSubjectListener() {                @Override                public void onGetInfo(String info) {                    mTvInfoFromObserver1.setText(info);                }            });        }        if (mObserver2 == null) {            mObserver2 = new Observer2();            mObserver2.setOnGetInfoFromSubjectListener(new OnGetInfoFromSubjectListener() {                @Override                public void onGetInfo(String info) {                    mTvInfoFromObserver2.setText(info);                }            });        }    }    private void initAction() {        mBtnSubscribe.setOnClickListener(this);        mBtnNotify.setOnClickListener(this);    }    private void initView() {        mTvInfoFromObserver1 = (TextView) findViewById(R.id.tv_info_from_observer1);        mTvInfoFromObserver2 = (TextView) findViewById(R.id.tv_info_from_observer2);        mBtnSubscribe = (Button) findViewById(R.id.btn_subscribe);        mBtnNotify = (Button) findViewById(R.id.btn_notify);    }    @Override    public void onClick(View view) {        int id = view.getId();        if (id == mBtnSubscribe.getId()) {            mRealSubject.subscribe(mObserver1);            mRealSubject.subscribe(mObserver2);        }        if (id == mBtnNotify.getId()) {            mRealSubject.sendInfo2Observer();        }    }}

然后源码传送门
观察者模式

原创粉丝点击