观察者模式

观察者模式

      定义了对象之间的一对多的关系,当一个对象状态改变,它的所有依赖的对象都会收到通知并且相应改变。

定义观察者模式的类图:

                  由主题和一个或多个观察者构成

    

可以看到,主题(subject)应该具有的方法有:

            addObserver()              //为主题添加观察者             deleteObserver()    //删除观察者             notifyObserver()     //通知观察者数据变化

    观察者(Observer)应该具有的方法:

              update()      //接收更新,并作出响应

以最常见的订报服务为例:

  1.报社的业务就是出版报纸

  2.向某家报社订阅报纸,只要他们有新的报纸出版,就会发送到客户,客户也就会收到新报纸。

  3.当客户不想再看报纸的时候,取消订阅,报社就不会送新报纸来。

  4.只要报社还在运营,就一定会提供订阅和取消订阅服务。

下面用一个简单的例子模拟:

  先列出核心类图:

    此实例定义了3个用户(Observer),并为用户提供了订报服务。通过用户注册报社(Subject)的订报服务,报社推送订报和用户取消订报服务来学习观察者模式的使用方法。

      

核心代码:

  Subject接口:

public interface Subject {
    public void deleteObserver(Observer obj);

    public void notifyObservers();

    void addObserver(Observer obj);

}

 

NewSbuject类:

public class NewsSubject implements Subject {
    private ArrayList<Observer> objs;
    private String chinese, english, math;
    
    
    public NewsSubject(){
        objs=new ArrayList<Observer>();
    }
    
    @Override
    public void addObserver(Observer obj) {
        // TODO Auto-generated method stub
        objs.add(obj);
        
    }

    @Override
    public void deleteObserver(Observer obj) {
        // TODO Auto-generated method stub
        objs.remove(obj);

    }

    @Override
    public void notifyObservers() {
        // TODO Auto-generated method stub
        System.out.println("报社有新内容更新了,发送更新");
        for(Observer temp:objs)
                temp.update( chinese, english, math);

    }
    //动态设置报纸内容
    public void setData(String chinese,String english,String math){
        this.chinese=chinese;
        this.english=english;
        this.math=math;
        notifyObservers();
        
    }

}

 

Observe接口:

public interface Observer {
        public void update(String chinese,String english,String math);
//这里添加了cancle()方法,用来模拟客户取消订报服务
        public void cancle();
}

 

ChineseObserver类:

  

 

public class ChineseObserver implements Observer, Preform {
    private String content;
    private Subject sub;

    public ChineseObserver(NewsSubject sub) {
        // 为观察者注册
        this.sub = sub;
        sub.addObserver(this);

    }

    @Override
    public void update(String chinese, String english, String math) {
        // TODO Auto-generated method stub
        content = chinese;
        display();

    }

    @Override
    public void display() {
        // TODO Auto-generated method stub
        System.out.println("B订的是语文报,新一期报纸的内容:" + content);
    }

    @Override
    public void cancle() {
        // TODO Auto-generated method stub
        sub.deleteObserver(this);
        System.out.println("B取消订报");
    }

}

其他的MathObserver,EnglishObserver与之类似。

主程序:

public class Main {
    static NewsSubject sub;
    static EnglishObserver eng;
    static ChineseObserver chi;
    static MathObserver mat;
    public static void main(String[] arg) {
        sub=new NewsSubject();
        eng=new EnglishObserver(sub);
        chi=new ChineseObserver(sub);
        mat=new MathObserver(sub);
        sub.setData("今天星期日", "stay hungry ,stay foolish!", "1+2=3");
        
        new  Thread(){
            public void run() {
                try {
                    sleep(4000);
                    System.out.println("一天过去了。");
                    mat.cancle();
                    sleep(4000);
                    System.out.println("一天过去了。");
                    sub.setData("今天要上学了!", "keep moving!", "10+10=20");
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                
            };
        }.start();
        
    }

}

运行可以看到结果:

报社有新内容更新了,发送更新
A订的是英语报,新一期报纸的内容:stay hungry ,stay foolish!
B订的是语文报,新一期报纸的内容:今天星期日
C订的是数学报报,新一期报纸的内容:1+2=3
一天过去了。
C取消订报
一天过去了。
报社有新内容更新了,发送更新
A订的是英语报,新一期报纸的内容:keep moving!
B订的是语文报,新一期报纸的内容:今天要上学了!

  通过这样就可以看到观察者模式的使用方法和运行形式,另外这个例子中只是实现报社主动推送报纸服务,可另外扩展为用户主动请求更新,这里不做实现,读者另行实现。同时Java有内置的观察者模式,通过java.util包内的Observer接口和Observable类来实现。不过只要你掌握的观察者模式,哪一种方法来实现也是易如反掌的。

 

 

 

posted on 2014-05-14 16:02  HelloCsl  阅读(362)  评论(0编辑  收藏  举报

导航