观察者模式

来源:互联网 发布:高达seed 知乎 编辑:程序博客网 时间:2024/06/06 10:38

我认为这个模式名称有先天的残疾!如果你确实理解了观察者模式你就能体会到了呀!

福尔摩斯老先生不止一次对华生说:“我是在观察,而你是在看”。人家福尔摩斯老先生那可真叫观察呀,对周围的事物简直观察到了及至了...

可观察者模式里的这群观察者可是不折不扣的懒汉!他们从不主动观察!他们只是等待被通知呢!所以我一直认为“订报模式”更能说明这个模式的意思,因为订报的人都很懒,他们就在家等着报纸送来。

所以我们就订报吧!一般订报的人都是想要了解最新的新闻,也就是说当报社出了新 报纸的时候,订报的人想要尽快的得到新的报纸,报社的责任就是包新出的报纸“及时”地传给“订阅了报纸”的读者们,你没订我的报纸,我给你,我傻啊?下面的例子就是订报呀:

报 社肯定有一个清单,这个清单上有订阅报纸的人的信息,姓名了,地址了什么的;我们再一“抽”(注意这里不是抽风是抽象),啊,不管报社还是杂志社都得有这 么一个清单啊,是不是应该抽象出一个“概念”来呀?是呀,这就是我们的主题啊,主题就是被观察的对象!再有啊,这个清单是动态的,可能随时有人订报,也可 能有人不订了,

还有不管你是读报啊,还是读杂志啊,都是观察者,至于你是不是个读者那得看你是不是实现了观察者接口,如果你给一个小狗类实现了观察者接口,那这个小狗就是一个观察者了,嘿嘿,废话少说,java上阵:

观察者接口,实现了这个接口的都叫观察者了,这就是本模式中所谓的观察者们(其实他们平时很懒的,嘿嘿):
package ob;

public interface Observer {
    public void update(); //有什么新情况,我就得更新一下,(如果有新报纸出来,我就读一下呗)
}

下面是我们的主题接口了,这个主题应该有签到,签出和通知的功能——订报,取消订报和发新报纸的功能,哈哈:
package ob;

imp

ort java.util.ArrayList;

public class NewspaperOffice implements Subject {
    
    private ArrayList<Observer> readers; //这个清单是报社的,别人谁都不能看,保护读者隐私呀,得!所以得private
    private String newspaper = ""; //这个串就代表报纸了吧
    
    public NewspaperOffice(){
        this.readers = new ArrayList<Observer>();
    }
    
    @Override
    public void checkIn(Observer o) {
        // TODO Auto-generated method stub
        //有个读者订了报,我们就把这个读者放到清单里,嘿嘿
        readers.add(o);
    }

    @Override
    public void checkOut(Observer o) {
        // TODO Auto-generated method stub
        //如果那个读者不想订报了,那就从清淡里除名!
        int i = readers.indexOf(o);
        if(i >= 0){
            readers.remove(i);
        }
    }

    @Override
    public void notifyThem() {
        // TODO Auto-generated method stub
        //如果我有新的报纸出了,我就得更新一下我的订阅者手里的报纸啦,嘿嘿
        for(int i=0;i < readers.size();i++){
            Observer reader = (Observer)readers.get(i);
            reader.update(); 
        }
    }
    
    //报社还得会生产新报纸,哈哈
    
    public void produceNewspaper(String newspaper){
        this.newspaper = newspaper; 
        //每当生产完了新报纸,我就要通知我的订阅者们并让他们更新手里的旧报纸,嘿嘿
        this.notifyThem();
    }
    
    public String getContent(){ //获得当前报纸的内容
        return this.newspaper;
    }
}

主题有了,可我们的观察者还没呢,我们有的只是一个接口,那我们就做一个读者吧,呵呵:

被忘了读者是观察者,所以要实现观察者接口:
package ob;

public class Reader implements Observer {
    
    private String name; //给读者起个名字
    private NewspaperOffice newspaperOffice;//本读者感兴趣的报社,哈哈
    private String mynewspaper = ""; //用户手里的报纸
    
    public Reader(String name ,NewspaperOffice newspaperOffice){ //读者不知道主题是什么玩意,他只对报社这个东西有兴趣
        this.name = name;
        this.newspaperOffice = newspaperOffice;
    }
    
    @Override
    public void update() {
        this.setNewsPaper();//先更新一下手里的报纸
        // 当读者收到新报纸的时候会有 什么反映呢?先叫一声吧:
        System.out.println("Hi All,我是"+ this.name +" 我的新报纸来了哦!让我看看有什么内容:");
        //看看有什么内容
        System.out.println(this.mynewspaper);//打开手里的报纸,看看
    }
    
    public void setNewsPaper(){ //更新用户手里的报纸,这可是报社的责任呀
        this.mynewspaper = newspaperOffice.getContent();
    }
    
    public void addMe(){ // 订报
        newspaperOffice.checkIn(this);
    }
    
    public void removeMe(){ // 不订了
        newspaperOffice.checkOut(this);
    }
}

好啦,测试一下,呵呵:

package ob;

public class ObTest {
    
    public static void main(String[] args){
        NewspaperOffice newspaperOffice = new NewspaperOffice(); //似乎少一个名字,你可以加上啊,毕竟有很多报社呀
        //下面是我们众多的读者,订阅了我们的报纸
        Reader Zhangsan = new Reader("张三",newspaperOffice);
        Reader Lisi = new Reader("李四",newspaperOffice);
        Reader Wangwu = new Reader("王五",newspaperOffice);
        Zhangsan.addMe();
        Lisi.addMe();
        Wangwu.addMe();
        newspaperOffice.produceNewspaper("火星出事啦!!");
        
        //张三这个家伙,这个时候不想收到报纸了,因为人家开始上网看新闻啦!所以
        Zhangsan.removeMe(); 
        
        newspaperOffice.produceNewspaper("原来是虚惊一场呀!");
    }
}

哈哈,只要一出新报纸,“订了报的”都会收到新报纸了...

原创粉丝点击