您的位置:首页 > 编程语言 > Java开发

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

2016-05-20 17:38 477 查看
不知道大家有没有注意到,生活中有很多时候,发生事件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("第三本书", "三毛");
}
}


输出结果:

我是读者读者一很高兴收到了大毛*第一本书

我是读者读者二很高兴收到了大毛*第一本书

我是读者读者一很高兴收到了二毛*第二本书

我是读者读者二很高兴收到了二毛*第二本书

我是读者读者一很高兴收到了三毛*第三本书

我是读者读者二很高兴收到了三毛*第三本书

以上。

如有不对请指出。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: