您的位置:首页 > 其它

设计模式之观察者模式

2015-09-19 17:52 435 查看
在介绍观察者模式之前,我先回忆一下小学时光的趣事,上小学的时候,那时候有自习课,老师就会会办公室休息,然而这是我们最快乐的时光,因为在这个时间里我们就可以玩牌了(play card),因为那时候没有现在科技这么发达,没有智能手机和IPAD等高端移动设备,那时候打扑克就是我们非常喜欢玩的娱乐活动,然而在自习课上打牌是老师和学校里禁止的(这个没听说学校提倡的),每到自习课,我们就想玩扑克,但是不敢大胆的玩啊,因为老师随时都可能来查自习的纪律,没办法,只能轮着看门,看门者的任务就是观察老师什么

时候到来,接着通知打牌的同学,相互合作嘛。

今天,临到赵同学看门,我们几个打牌,自习课上,赵同学自觉的到自己的岗位上,通过窗户望着前方,时刻观察者前方是否有老师出现的动态,我们(钱同学,刘同学)几个就开始高兴的玩牌了

在这里赵同学就是具体主题的通知者,我们就是具体的观察者。

主题通知者的抽象行为:

package com.panther.dong.designpattern.observer;

/**
 * observer subject(abstract notice)
 * Created by panther on 15-9-19.
 */
public interface Subject {

    public void add(Observer observer);

    public void drop(Observer observer);

    public void notice();
}
主题通知者的具体实现:

package com.panther.dong.designpattern.observer;

import java.util.ArrayList;
import java.util.List;

/**
 * zhao负责看门(观察老师的到来)(具体的主题)
 * Created by panther on 15-9-19.
 */
public class SubjectZ implements Subject {
    private List<Observer> observerList = new ArrayList<>();

    //任何一个想打牌的同学都和zhao说,老师来了通知他
    @Override
    public void add(Observer observer) {
        observerList.add(observer);
    }

    //其中一个同学和zhao关系不好,zhao不通知他
    @Override
    public void drop(Observer observer) {
        observerList.remove(observer);
    }

    @Override
    public void notice() {
        for (Observer observer : observerList) {
            observer.update();
        }
    }
}


打牌的人就是具体的观察者,他们最想知道老师是否到来的动态

抽象观察者:

package com.panther.dong.designpattern.observer;

/**
 * 抽象的观察者
 * Created by panther on 15-9-19.
 */
public interface Observer {
    public void update();
}


具体的实现(钱同学)

package com.panther.dong.designpattern.observer;

/**
 * 具体的观察者
 * Created by panther on 15-9-19.
 */
public class ObserverQ implements Observer{
    @Override
    public void update() {
        System.out.println("钱,拿出数学题目做题");
    }
}


具体的实现(刘同学)

package com.panther.dong.designpattern.observer;

/**
 * 具体的观察者
 * Created by panther on 15-9-19.
 */
public class ObserverL implements Observer {
    @Override
    public void update() {
        System.out.println("刘,拿出课本来读书");
    }
}


客户端调用逻辑:

package com.panther.dong.designpattern.observer;

/**
 * client implement
 * Created by panther on 15-9-19.
 */
public class Client {
    public static void main(String[] args) {
        System.out.println("----------------------------------");
        //赵看门
        Subject subjectZ = new SubjectZ();

        ObserverL observerL = new ObserverL();
        ObserverQ observerQ = new ObserverQ();
        //刘和钱打牌,告诉赵老师来了叫他们
        subjectZ.add(observerL);
        subjectZ.add(observerQ);
        //老师来了,刘和钱收到赵的通知
        subjectZ.notice();
        System.out.println("----------------------------------------");
        //假设赵和刘关系不好,老师来了赵通知钱,但是不通知刘
        subjectZ.drop(observerL);
        subjectZ.notice();//只有钱收到通知,刘收不到通知
        System.out.println("------------------------------------------");

    }
}


结果输出:



这就是一个简单的观察者设计模式的应用,具体的关系类图为:



观察者定义:观察者又叫做发布/订阅模式(publish/subscribe)模式。

观察者定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在发生变化的时候,会通知所有的观察者对象,是他们能够自动更新自己

上面的例子中,赵同学看到老师来了之后,就会通知钱同学和刘同学,接着钱同学和刘同学就会停止打牌的动作,转向学习!!!

几个观察者的名词:

  抽象主题角色:把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。(上面的Subject接口)

  抽象观察者角色:为所有具体的观察者定义一个接口,在得到主题的通知时更新自己。(上面的Observer接口)

  具体主题角色:在具体主题内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个子类实现。(上面的上面的SubjectZ类)

  具体观察者角色:该角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。通常用一个子类实现。如果需要,具体观察者角色可以保存一个指向具体主题角色的引用。(上面的ObserverL和ObserverQ类)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: