Java设计模式——观察者模式

不知道大家有没有注意到,生活中有很多时候,发生事件A就会触发事件B。
还记得上学的时候吗,每当在课堂上偷偷睡觉的时候,总是会让同桌在老师过来的时候叫醒自己。这实际上就是同桌充当了“观察者”,而你充当了“订阅者”的角色,一旦“老师来了”这件事情发生,你的同桌就会“向你发送消息”通知你老师来了。这实际上就是一套“观察者模式的流程”
观察者模式定义了对象间的一种一对多依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
下面以一个小程序来举例子
假如我们要做一个订报的小程序,每当报社发布了一本新书,读者就会收到新书消息的通知。
经过一番思考之后,决定这样设计:定义一个读者类和报社类。
报社类需要有订阅读者的列表,添加或者移除读者的方法,通知所有订阅者的方法,更新书本信息的方法。
读者类中需要有接受报社传递的信息的方法。
然后写出了如下代码:

public class NewsOffice
{
//报社类
    List<Reader> readers;
    public String bookname;
    public String writer;
    public NewsOffice()
    {
        readers = new ArrayList<>();
    }
//注册读者
    public void addReader(Reader reader)
    {
       readers.add(reader);
    }
    //移除读者
    public void removeReader(Reader reader){
        int index=readers.indexOf(reader);
        if (index>0)
        {
            readers.remove(index);
        }
    }
    //通知所有注册的读者有新书了
    public void notifyAllObserver(){
        for(Reader reader:readers){
            reader.update(writer+"***"+bookname);
        }
    }
    //设置新书的信息
    public void setInformation(String bookname,String writer){
    this.bookname=bookname;
    this.writer=writer;
    notifyAllObserver();
    }
}
public class Reader
{
    String readername;
    String bookinformation;
    public Reader(String readername)
    {
        this.readername = readername;
    }
    public void update(String bookinformation)
    {
        this.bookinformation=bookinformation;
        display();
    }
    private void display()
    {
        System.out.print("我是读者"+readername+"很高兴收到了");
        System.out.println(bookinformation);
    }
}
public class Test
{
    public static void main(String[] a)
    {
        NewsOffice newsOffic = new NewsOffice();
        Reader reader1 = new Reader("读者一");
        Reader reader2 = new Reader("读者二");
        newsOffic.addReader(reader1);
        newsOffic.addReader(reader2);
        newsOffic.setInformation("第一本书", "大毛");
        newsOffic.setInformation("第二本书", "二毛");
        newsOffic.setInformation("第三本书", "三毛");
    }
}

输出结果如下:
我是读者读者一很高兴收到了大毛*第一本书
我是读者读者二很高兴收到了大毛*第一本书
我是读者读者一很高兴收到了二毛*第二本书
我是读者读者二很高兴收到了二毛*第二本书
我是读者读者一很高兴收到了三毛*第三本书
我是读者读者二很高兴收到了三毛*第三本书

这时候看起来似乎结果还是很满意的,符合系统设计的预期。
但是不知道大家有没有发现,这是针对实现变成而不是针对接口编程。
如果添加了新的类型的读者,报社需要增加新的代码来适配新的读者。

这时候可以使用今天要介绍的”观察者模式“来实现
关于观察者的一切,主题只需要知道观察者实现了观察者接口,主题不需要知道观察者的具体实现。任何时候我们都可以增加或者删除观察者,主题不会受到任何影响。
有新的类型的观察者出现时,主题不需要任何的修改,只要观察者实现了观察者接口,即可注册成为观察者。主题和观察者这种松耦合的设计,可以应对各种场合。

首先创建观察者和主题。

public interface Observer
{
//使用Update方法接收传递的书本信息
    public void update(String bookname);

}
public interface Supervisor
{
//增加观察者
public void addObserver(Observer observer);
//移除观察者
public void removeObserver(Observer observer);
//通知所有观察者
public void notifyAllObserver();
}

创建报社类实现主题接口

public class NewsOffice implements Supervisor
{
public List<Observer> observers;
public String bookname;
public String writer;
    public NewsOffice()
{
    observers=new ArrayList<Observer>();

}

    @Override
    public void addObserver(Observer observer)
    {
    observers.add(observer);    
    }

    @Override
    public void removeObserver(Observer observer)
    {
        int i=observers.indexOf(observer);
        if (i>0)
        {
            observers.remove(i);
        }
    }

    @Override
    public void notifyAllObserver()
    {
    //遍历所有的观察者发送消息
        for(Observer observer:observers){
            observer.update(writer+"***"+bookname);
        }
    }
    public void setInformation(String bookname,String writer){
    //更新书本的信息,并且将更新的信息通过notifyAllObserver传递给观察者
        this.bookname=bookname;
        this.writer=writer;
        notifyAllObserver();
    }
}
public class Reader implements Observer
{
    private String bookinformation;
    private String readername; 

    public Reader(String readername)
    {
        this.readername = readername;
    }

    @Override
    public void update(String bookinformation)
    {
        this.bookinformation = bookinformation;
        display();
    }

    private void display()
    {
        System.out.print("我是读者"+readername+"很高兴收到了");
        System.out.println(bookinformation);
    }
}

测试类如下

public class Test {
    public static void main(String[] a)
    {
        NewsOffice newsOffic = new NewsOffice();
        Reader reader1 = new Reader("读者一");
        Reader reader2 = new Reader("读者二");
        newsOffic.addObserver(reader1);
        newsOffic.addObserver(reader2);
        newsOffic.setInformation("第一本书", "大毛");
        newsOffic.setInformation("第二本书", "二毛");
        newsOffic.setInformation("第三本书", "三毛");
    }
}

输出结果:
我是读者读者一很高兴收到了大毛*第一本书
我是读者读者二很高兴收到了大毛*第一本书
我是读者读者一很高兴收到了二毛*第二本书
我是读者读者二很高兴收到了二毛*第二本书
我是读者读者一很高兴收到了三毛*第三本书
我是读者读者二很高兴收到了三毛*第三本书

以上。
如有不对请指出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值