架构之路

设计模式——观察者模式

2016-12-30  本文已影响15人  SyncAny

简述

简单来说,观察者模式可以这样理解:定义对象间的一种一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都能得到通知并被自动更新。


情景模式

上面描述过于官方,不容易理解,所以我们可以放到某种情景中去就容易理解了。


比如:在简书上有某位作者的文章我很喜欢,但是呢,我不知道他什么时候会更新文章,我也不会每隔一段时间去刷新一下,看看他有没有发布新的文章,这样太累了。所以我可以选择关注这位作者,当他有新的文章发布时,我就会收到一个推送消息,告诉我新文章上线了,可以去欣赏一下了;如果哪天我不想接收他的新文章上线的推送,那我对他取消关注就可以了。


实例

1. 关键元素

上述的情景中,我们可以发现三个比较重要的环节:关注、推送、取消关注;
这个和观察者模式也是相对应的:注册(订阅)、反注册(取消订阅)、通知改变数据。

2. 代码实例
(1). 定义被观察者(非接口模式)
/*
*  被观察者
*  一般被观察者被定义为接口,然后其他类去继承并实现其中的方法,
*  这里换种方式,直接在被观察者中实现方法
*/
public class Observable<T> {
//观察者的集合
    private List<Observer<T>> observers = new ArrayList<Observer<T>>();
//注册
    public void register(Observer<T> observer) {
        if (observers != null && !observers.contains(observer)) {
            observers.add(observer);
        }
    }
//取消注册
    public void unregister(Observer<T> observer) {
        if (observers != null) {
            observers.remove(observer);
        }
    }
//通知所有观察者数据发生了改变
    public void notifyAllObserver(T data) {
        for (Observer<T> observer : observers) {
            observer.bookUpdate(observer, data);
        }
    }
//通知单个观察者数据发生了改变
    public void notifyObserver(Observer<T> observer, T data) {
        observer.bookUpdate(observer, data);
    }

}
(2). 定义观察者(接口模式)
/*
*  观察者,数据更新的接口
*/
public interface Observer<T> {
    void bookUpdate(Observer<T> observer,T data);
}
(3). 实体类(如果被观察者是接口形式的,可以继承被观察者,实现里面的方法)
/*
*  实体类,可以继承接口形式的被观察者Observeable
*/
public class Books {
    private String bookName;
    private String bookPrice;
    public String getBookName() {
        return bookName;
    }
    public void setBookName(String bookName) {
        this.bookName = bookName;
    }
    public String getBookPrice() {
        return bookPrice;
    }
    public void setBookPrice(String bookPrice) {
        this.bookPrice = bookPrice;
    }
    
    @Override
    public String toString() {
        return "welcome! The book "+bookName+" is update, price is $"+bookPrice;
    }
}
(4). 具体实现(只包含主要代码)
/*
*  这个方法主要是初始化数据,
*/
private void initData() {
       //实例化一个被观察者
        observable = new Observable<Books>();
        //实例化观察者1
        observer1 = new Observer<Books>() {
            @Override
            public void bookUpdate(Observer<Books> observer, Books data) {
                System.out.println("观察者1 :" + data.toString());
            }

        };
        //实例化观察者2
        observer2 = new Observer<Books>() {
            @Override
            public void bookUpdate(Observer<Books> observer, Books data) {
                System.out.println("观察者2 :" + data.toString());
            }

        };
        //实体类数据赋值
        books1 = new Books();
        books1.setBookName("冬天的席丽拓");
        books1.setBookPrice("122");

        books2 = new Books();
        books2.setBookName("空的.上午");
        books2.setBookPrice("24");
        
        books3 = new Books();
        books3.setBookName("单独的更新");
        books3.setBookPrice("85");
}



/*
*  点击时间中实现注册与反注册,并通知数据改变
*/
@Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.register:
            //注册
            observable.register(observer1);
            observable.register(observer2);
            //通知数据改变
            observable.notifyAllObserver(books1);
            observable.notifyAllObserver(books2);

            //这个是单独通知观察者1,数据改变了
            observable.notifyObserver(observer1, books3);
            break;
        case R.id.unregister:
       //取消观察者1的注册,保留观察者2的注册,发动通知后,只有观察者2可以收到消息
            observable.unregister(observer1);
            observable.notifyAllObserver(books1);
            observable.notifyAllObserver(books2);
            break;
        default:
            break;
        }
    }
(5). 通知结果

1.第一次注册


第一次注册.png

2.取消注册


取消注册.png

3.再一次注册

再次注册.png
观察结果:

(1) 第一次注册并发送通知,两个观察者都收到了消息,并且观察者1一共有3条消息,观察者2两条消息。
(2) 取消观察者1的注册并发送通知,只有观察者2收到了两条消息
(3) 再次注册并发送通知,两个观察者都收到了消息,并且观察者1一共有3条消息,观察者2两条消息,但是请注意红色框中的观察者的顺序有所改变。

总结

观察者模式总结过来最大的是抓住三个要素:注册(订阅)、反注册(取消订阅)、通知改变数据。
实际的开发中遇到的情况相比这个例子要复杂很多,但是只要理解了观察者模式的这种实现方式与思想,很多复杂的事情就变得简单了。(以上纯属个人理解,如有错误的地方,烦请指正,感谢!)

上一篇 下一篇

猜你喜欢

热点阅读