观察者模式(Observer Pattern):当一个对象被修改时,会自动通知它的依赖对象
现在我们是新闻社,要向所有新闻订阅者推送新闻。那么该如何实现呢?
经过思考我们不难发现一家新闻社一般对应的是多个新闻订阅者。
那么我们先从新闻社开始入手,想一想新闻社要具备哪些基本功能呢?
1.新闻,2.有哪些订阅者,3.添加订阅者,4.取消订阅者,5推送新闻。
//新闻社
public class Newspaper {
private String news;//新闻
public List<Subscriber> subscribers = new ArrayList<>();//存储所有订阅者
public void addSubscriber(Subscriber subscriber){//添加订阅者
subscribers.add(subscriber);
}
public void removeSubscriber(Subscriber subscriber){//删除订阅者
subscribers.remove(subscriber);
}
public void sendNews(){//给所有订阅者发送新闻,此处可以改进,后面讲到
for (Subscriber subscriber : subscribers) {
subscriber.receiveNews(news);
}
}
public String getNews() {
return news;
}
public void setNews(String news) {
this.news = news;
}
}
新闻社已经规划好,现在考虑订阅者,订阅者是多个,那么我们先定义一套订阅者的标准(接口),并考虑订阅者需要做的事:
1.接收新闻
//订阅者
public interface Subscriber {
void receiveNews(String news);//接收新闻
}
标准写好了,现在有两个客户联系上我们,要成为我们的订阅者:
//订阅者One
public class SubscriberOne implements Subscriber{
@Override
public void receiveNews(String news) {
System.out.println("订阅者One,接收到新闻:"+news);
}
}
//订阅者Two
public class SubscriberTwo implements Subscriber{
@Override
public void receiveNews(String news) {
System.out.println("订阅者Two,接收到新闻:"+news);
}
}
规划了新闻社,与订阅者签了合同,现在来实际操作一下:
public static void main(String[] args) {
//建立真正的新闻社
Newspaper newspaper = new Newspaper();
//将订阅者One加入
newspaper.addSubscriber(new SubscriberOne());
//将订阅者Two加入
newspaper.addSubscriber(new SubscriberTwo());
//设置新闻
newspaper.setNews("70周年");
//发送新闻
newspaper.sendNews();
}
观察者模式(推模型),运行结果:
订阅者One,接收到新闻:70周年
订阅者Two,接收到新闻:70周年
不难发现,这个设置新闻和发送新闻,其实可以整合一下,第一种直接发送新闻内容就行,第二种设置新闻时,自动推送给所有订阅者,但是都还属于推模型,先来实现第一种,改造新闻社:
//新闻社
public class Newspaper {
public List<Subscriber> subscribers = new ArrayList<>();//存储所有订阅者
public void addSubscriber(Subscriber subscriber){//添加订阅者
subscribers.add(subscriber);
}
public void removeSubscriber(Subscriber subscriber){//删除订阅者
subscribers.remove(subscriber);
}
public void sendNews(String news){//直接给所有订阅者发送新闻★★★
for (Subscriber subscriber : subscribers) {
subscriber.receiveNews(news);
}
}
}
重新运行下:
public static void main(String[] args) {
//建立真正的新闻社
Newspaper2 newspaper = new Newspaper2();
//将订阅者One加入
newspaper.addSubscriber(new SubscriberOne());
//将订阅者Two加入
newspaper.addSubscriber(new SubscriberTwo());
//直接发送新闻
newspaper.sendNews("70周年");
}
结果一致:
订阅者One,接收到新闻:70周年
订阅者Two,接收到新闻:70周年
现在来实现第二种,改造新闻社:
//新闻社
public class Newspaper{
private String news;//新闻
public List<Subscriber> subscribers = new ArrayList<>();//存储所有订阅者
public void addSubscriber(Subscriber subscriber){//添加订阅者
subscribers.add(subscriber);
}
public void removeSubscriber(Subscriber subscriber){//删除订阅者
subscribers.remove(subscriber);
}
public void sendNews(){//给所有订阅者发送新闻
for (Subscriber subscriber : subscribers) {
subscriber.receiveNews(news);
}
}
public String getNews() {
return news;
}
public void setNews(String news) {
this.news = news;
sendNews();//在设置新闻时,自动推送给所有订阅者★★★
}
}
重新运行一下:
public static void main(String[] args) {
//建立真正的新闻社
Newspaper3 newspaper = new Newspaper3();
//将订阅者One加入
newspaper.addSubscriber(new SubscriberOne());
//将订阅者Two加入
newspaper.addSubscriber(new SubscriberTwo());
//设置新闻,并自动推送
newspaper.setNews("70周年");
}
运行结果一致:
订阅者One,接收到新闻:70周年
订阅者Two,接收到新闻:70周年
以上是推模型的实现方法,那什么是拉模型呢?先看这两个地方:
新闻社推送的都是新闻,并且订阅者订阅的是新闻的内容。我们是否可以不推新闻,而是把新闻社提供给订阅者,需要时订阅者自己去获取新闻呢?下面重新改造一下:
//新闻社
public class Newspaper {
private String news;//新闻
public List<Subscriber> subscribers = new ArrayList<>();//存储所有订阅者
public void addSubscriber(Subscriber subscriber){//添加订阅者
subscribers.add(subscriber);
}
public void removeSubscriber(Subscriber subscriber){//删除订阅者
subscribers.remove(subscriber);
}
public void sendNewspaper(){//提供的不再是新闻,而是新闻社★★★
for (Subscriber subscriber : subscribers) {
subscriber.receiveNewspaper(this);//将自己提供给订阅者
}
}
public String getNews() {
return news;
}
public void setNews(String news) {
this.news = news;
sendNewspaper();//设置新闻时,将新闻社提供给订阅者★★★
}
}
//订阅者定义
public interface Subscriber {
void receiveNewspaper(Newspaper newspaper);//接收新闻社★★★
}
//订阅者One
public class SubscriberOne implements Subscriber{
@Override
public void receiveNewspaper(Newspaper newspaper) {
String news = newspaper.getNews();//订阅者One自行从新闻社获取新闻★★★
System.out.println("订阅者One,接收到新闻:"+news);
}
}
//订阅者Two
public class SubscriberTwo implements Subscriber{
@Override
public void receiveNewspaper(Newspaper newspaper) {
String news = newspaper.getNews();//订阅者Two自行从新闻社获取新闻★★★
System.out.println("订阅者Two,接收到新闻:"+news);
}
}
拉模型已经写好,现在运行一下:
public static void main(String[] args) {
//建立真正的新闻社
Newspaper newspaper = new Newspaper();
//将订阅者One加入
newspaper.addSubscriber(new SubscriberOne());
//将订阅者Two加入
newspaper.addSubscriber(new SubscriberTwo());
//设置新闻
newspaper.setNews("70周年");
}
运行结果
订阅者One,接收到新闻:70周年
订阅者Two,接收到新闻:70周年