观察者模式(推模型+拉模型)

观察者模式(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周年
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值