设计模式之观察者模式

来源:互联网 发布:阿里云pc 编辑:程序博客网 时间:2024/06/07 04:55

        写作缘由:对于一个有逼格的程序猿,23种设计模式应该不在话下,为了挤身逼格程序猿之列,决定系统的学习设计模式

        关于设计模式(主要是思想方面)

               001.定义:

                               是一套反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结

               002.目的:

                               为了可重用代码、让代码更容易被他人理解、保证代码可靠性

        设计模式之观察者模式:

               定义:定义了对象之间的一种一对多的关系,当一个对象的状态发生改变时,所有依赖它的对象都得到通知并被自动更新(其实就是1对n,当“1”发生变化时,“n”全部得到通知,并更新)

               应用场景:

                      小区住户预订牛奶,只要你预定了牛奶,他就会在每天早上7:30送到你家楼下

                      微信关注的公众号,只要订阅了公众号,当公众号内容发生类变化,订阅过的人们都会得到更新的内容

                      订阅天气预报,每天都会有更新提醒你最新的天气情况

                      ...

              Android中的应用场景:

                     ListView的适配器,有个函数notifyDataSetChanged()函数,这个函数其实就是通知ListView的每个Item,数据源发生了变化,请各位Item重新刷新一下

                     Eventbus的应用,详细就不说了,可自行查阅,这个库是对观察者模式很好的应用

                     ...

              下面开始观察者模式学习:

                     1).认识观察者模式:6大方面

                               001.目标与观察者之间的关系:

                                                              a.观察者与目标对象是一对一关系    

                                      b.一个目标对应多个观察者

                                     c .一个观察者对应多个目标(这种情况下,建议观察者对不同观察目标定义不同的回调,还可以在update方法内部区别不同的目标对象)

                                     

                                002.单向依赖:

                                        观察者依赖目标对象,只有目标对象知道什么时候通知观察者,观察者被动的等待通知并执行更新

                                003.命名的建议:

                                       a.目标接口的定义,建议在名称后面跟上subject

                                       b. 观察者接口的定义,建议在名称后面跟上Observer

                                       c.观察者接口的更新方法,建议名称为update

                                004.触发通知的时机:完成状态维护之后触发(数据设置完成之后)

                                005.观察者模式调用示意图:

                   准备阶段:

             

                                   

                  运行阶段:

                            

 

                              006.通知顺序:

                                     当目标状态改变时,通知各个观察者顺序不确定,所以各个观察者之间不应该有先后依赖关系

                     2).观察者模式的实现方式:

                            推模型:不管观察者是否需要,类似有广播通信

                                   目标对象主动向观察者推送目标的详细信息,推送的信息通常是目标对象的全部或部分数据

                            拉模型:

                                   目标对象在通知观察者的时候,只传递少量信息

                                   如果观察者需要更具体的信息,由观察者主动到目标对象中获取,相当于是观察者从目标对象中拉取数据

                                   一般这种模型的实现中,会把目标对象的自身通过update方法传递给观察者

                            两种模型的比较:

                                    推模型是假定目标对象知道观察者的数据

                                    拉模型是目标对象不知道观察者具体需要什么数据,因此把自身传递给观察者,由观察者来取值

                                    推模型会使观察者对象难以复用

                                    拉模型下,update方法的参数是目标对象本身,基本上可以适应各种情况的需要

                                  

                      3).观察者的优点:

                             观察者模式实现了观察者和目标之间的抽象耦合

                             观察者模式实现了动态联动

                             观察者模式支持广播通信

                      4).可能引起无谓的操作(需要在具体场景做以处理)

                      5).何时使用观察者模式:

                             a.当一个抽象模型有两个方面,其中一个方面的操作依赖于另一个方面的状态变化

                             b.如果在更改一个对象的时候,需要同时连带改动其他的对象,而且不知道究竟应该有多少对象需要被连带改变

                             c.当一个对象必须通知其他的对象,但是你又不希望这个对象和其他被它通知的对象是松散耦合的

                     

             放大招的时候到了------->>>上代码

             案例情景还原:黄明为她女朋友和丈母娘提供天气预报的订阅,并给她们不同信息回馈

             目标对象:

/** * 目标对象:它知道观察者它的观察者,并提供注册(添加)和删除观察者的接口 * (具体的目标类来继承实) */public class WeatherSubject {    //需要一个集合维护观察者的列表:用来保存注册的观察者对象    private List<Observer> mObservers = new ArrayList<>();    //attach:把订阅天气的人添加到列表中    public void attach(Observer observer) {//把观察者添加到观察者集合当中        mObservers.add(observer);    }    //detach:删除集合中指定的订阅天气的人    public void detach(Observer observer) {        mObservers.remove(observer);    }    //notify:通知所有已经订阅天气的人,这个方法只有子类可以调用    protected void notifyObservers() {//向所有已注册的观察者发生消息        for (Observer observer : mObservers) {            //在目标的Subject中调用update,            observer.update(this);//将Subject对象传给观察者,以便获取目标的状态        }    }}

             具体的目标对象:

/** * 具体的目标对象:负责把有关状态存入到相应的观察者对象当中 */public class ConcreateWeatherSubject extends WeatherSubject {    //目标天气的内容信息    private String weatherContent;    public String getWeatherContent() {        return weatherContent;    }    //在保存目标状态的时候通知观察者    public void setWeatherContent(String weatherContent) {        this.weatherContent = weatherContent;        //内容有了,说明天气更新了,通知所有订阅的人        this.notifyObservers();//状态发生改变就通知观察者    }}

             观察者接口:

/** * 观察者接口:定义一个更新的接口给哪些在目标发生改变的时候被通知的对象 */public interface Observer {    /**     * 更新的接口:     * @param subject 传入的目标的对象:方便获取相应的目标对象的状态     */    void update(WeatherSubject subject);}

               具体的观察者对象:

/** * 具体的观察者对象:实现更新的方法,使自身的状态和目标的状态保持一致 */public class ConcreateObserver implements Observer {    private static final String TAG = "ConcreateObserver";    //观察者的名字,是谁收到了这个信息,黄明的女朋友还是她老妈    private String observerName;    //天气的内容,这个消息从目标出获取    private String weatherContent;    //提醒的内容:黄明的女朋友提醒约会,而她老妈则提醒购物    private String remindThing;    public String getObserverName() {        return observerName;    }    public void setObserverName(String observerName) {        this.observerName = observerName;    }    public String getWeatherContent() {        return weatherContent;    }    public void setWeatherContent(String weatherContent) {        this.weatherContent = weatherContent;    }    public String getRemindThing() {        return remindThing;    }    public void setRemindThing(String remindThing) {        this.remindThing = remindThing;    }    //获取目标类的状态同步到观察者的状态    @Override    public void update(WeatherSubject subject) {        //取出目标状态覆盖观察者的状态,使2者同步        //强转为具体的ConcreateSubject,因为状态保持在子类中,通过子类获取状态        weatherContent = ((ConcreateWeatherSubject)subject).getWeatherContent();        Log.i(TAG, "update: " + observerName + "收到了" + weatherContent + "," + remindThing);    }
        

            测试(调用这个方法即可):标准4步走

private void observer() {    //1.创建目标    ConcreateWeatherSubject weather = new ConcreateWeatherSubject();    //2.创建观察者    ConcreateObserver observerGirl = new ConcreateObserver();    observerGirl.setObserverName("黄明的女朋友");    observerGirl.setRemindThing("我们的第一次约会,地点街心公园,不见不散哦");    ConcreateObserver observerMum = new ConcreateObserver();    observerMum.setObserverName("老妈");    observerMum.setRemindThing("是一个购物的好日子,明天去天虹扫货");    //3.注册观察者    weather.attach(observerGirl);    weather.attach(observerMum);    //4.目标发布天气    weather.setWeatherContent("明天天气晴朗,蓝天白云,气温28");}

           Last:本篇参照慕课网视频学习,有不懂的可以去慕课网看视频学习!

           

           欢迎探讨学习,真心希望大家推荐好文共同成长!