后续我会陆陆续续更新设计模式的一些介绍、应用、以及原理的文档。大家如果觉得对自己有用就点个关注吧。
引言
本文中的例子我尽量写的简单,避免一些我平时查资料时一些例子中出现的大量无用代码,产生让人阅读不下去的感觉
观察者模式
我会尽量用最简洁的代码将,观察模式逻辑体现出来.其实很简单,我们废话少说,直接上代码.
问题描述
说起观察者模式,我们经典的例子就是公众号关注问题,有人关注我的公众号,当我公众号内容更新的时候怎么才能自动的将这些更新信息发给各个用户呢,下面我们看一下这个功能的简单实现,(代码很简单不要慌)
1. 创建一个信息类
这个只是一个推送消息的类,小伙伴们不要慌
package designpattern.observerpattern.module;
import java.util.Date;
/**
* @author: wangxu
* @date: 2020/4/13 16:52
*/
public class News{
//公众号内容
private String info;
//公众号日期
private Date date = new Date();
//公众号内容标表体
private String title;
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Override
public String toString() {
return "News{" +
"info='" + info + '\'' +
", date=" + date +
", title='" + title + '\'' +
'}';
}
}
创建一个主题接口(也就是公众号要实现的接口),这个接口就比较关键了,不过在关键也不过是一个接口.
package designpattern.observerpattern.inter;
/**
* @author: wangxu
* @date: 2020/4/13 16:07
*
* 这是一个主题的接口,所有主题都要实现这个类:
* 注:观察者模式中java也有提供,只不过提供是一个类.而不是接口
*/
public interface Subject {
public void registerObserver(Observer observer);
public void removeObserver(Observer observer);
public void notifyObserver();
}
接下来新建几个用户来关注(观察)公众号用
2. 新建一个用户接口
package designpattern.observerpattern.inter;
import designpattern.observerpattern.module.News;
/**
* @author: wangxu
* @date: 2020/4/13 16:07
*
* 这个接口是更新数据的用的.所有观察者都要实现这个接口(典型的面向接口编程)
* 这个位置需要注意的是:
* 1.我们假设观察的对象是一个新闻对象.所以这里面的参数是News.
* 2.对于这个方法我们采取的是推的模式,推送新消息.(就是主题更新后的内容全都发给你,无论你需不需要;
* 对应的我们有一个拉的模式---每一个观察者会在你更新以后的对象中,自己获取所需变量)
*/
public interface Observer {
//推模式
public void update(News news);
}
3. 创建几个用户用于观察公众号
第一个用户
package designpattern.observerpattern.observer;
import designpattern.observerpattern.inter.Display;
import designpattern.observerpattern.inter.Observer;
import designpattern.observerpattern.inter.Subject;
import designpattern.observerpattern.module.News;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
/**
* @author: wangxu
* @date: 2020/4/13 16:31
* 注意这个位置我们实现了 Observer 你继续看你就会发现,
* 当公众号有内容更新的时候就是靠这个方法把最新的New对象推个订阅者的
*/
public class OneObserver implements Observer{
//这个变量没有什么实际意义
private String makeUpInfo;
//主题对象(就是微信公众号)此时我们获取到了公众号
private Subject news;
public OneObserver(Subject news){
this.news = news;
//关注这个公众号
news.registerObserver(this);
}
//通过推的模式给的更新内容.
@Override
public void update(News news) {
DateFormat sdf = new SimpleDateFormat("YYYY/MM/DD");
makeUpInfo = "观察者一最新内容如下-> -> 标题: 【观察者一不需要标题】 内容: " + news.getInfo() + " 时间: " + sdf.format(news.getDate());
show();
}
@Override
public void show() {
System.out.println(makeUpInfo);
}
}
第二个用户
package designpattern.observerpattern.observer;
import designpattern.observerpattern.inter.Display;
import designpattern.observerpattern.inter.Observer;
import designpattern.observerpattern.inter.Subject;
import designpattern.observerpattern.module.News;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
/**
* @author: wangxu
* @date: 2020/4/13 16:55
*/
public class TwoObserver implements Observer{
private String makeUpInfo;
//主题对象
private Subject news;
//当这个对象被创建出来的时候,就会自己订阅公众号
public TwoObserver(Subject news){
this.news = news;
news.registerObserver(this);
}
//通过推的模式给的更新内容.
@Override
public void update(News news) {
DateFormat sdf = new SimpleDateFormat("YYYY/MM/DD");
makeUpInfo = "观察者二最新内容如下-> -> 标题: " + news.getTitle() + " 内容: 【观察者二不需要内容】 时间: " + sdf.format(news.getDate());
show();
}
@Override
public void show() {
System.out.println(makeUpInfo);
}
}
开始创建一个公众号类(这个类是需要被观察(关注)的)
4. 创建公众号类
这个位置其实你仔细看就不难了.无非就是在反复的用多态.典型的面向接口编程(设计模式的中提倡的思想 “面向接口编程”)
package designpattern.observerpattern.theme;
import designpattern.observerpattern.inter.Observer;
import designpattern.observerpattern.inter.Subject;
import designpattern.observerpattern.module.News;
import java.security.PrivateKey;
import java.util.ArrayList;
import java.util.List;
/**
* @author: wangxu
* @date: 2020/4/13 16:15
* 新闻主题(被观察者)
*/
public class NewsTheme implements Subject {
//观察者集合
private List<Observer> observerList;
private News news;
public void setNews(News news) {
this.news = news;
}
/**
* 对象被创建时,同时创建观察者列表(容器)
*/
public NewsTheme() {
//观察列表
observerList = new ArrayList<>();
}
/**
* 注册观察者
* 这个位置配合上面的用户类看,你就会发现所谓的订阅,无非就是将这个用户对象放到自己的用户列表中
* List<Observer> observerList; 你如果理解了这一步,下面就很好理解了,无非就是对这个集合的增删改查
*/
@Override
public void registerObserver(Observer observer) {
observerList.add(observer);
}
/**
* 移除观察
*/
@Override
public void removeObserver(Observer observer) {
int i = observerList.indexOf(observer);
observerList.remove(i);
}
/**
* 新消息通知
*/
@Override
public void notifyObserver() {
observerList.stream().forEach(x -> x.update(news));
}
}
5. 开始执行测试
这里面顺便提一嘴,你们觉得这个公众号在创建了以后,他的生命周期是多长,这样的生命周期是否合理
/**
* @author: wangxu
* @date: 2020/4/13 17:07
*/
public class main {
public static void main(String[] args) {
News news = new News();
news.setDate(new Date());
news.setInfo("今天气温22.5度");
news.setTitle("天气预报");
//一旦开始调用这个方法,这个公众号里面的观察者列表就初始化了
NewsTheme newsTheme = new NewsTheme();
//注册观察者
OneObserver oneObserver = new OneObserver(newsTheme);
TwoObserver twoObserver = new TwoObserver(newsTheme);
//更新新闻对象
newsTheme.setNews(news);
//由于上一步我们更新了我们公众号里面的新闻,所以准备推送给各个订阅我的用户了,通知观察者
newsTheme.notifyObserver();
}
}
如果这块看不懂请多看几遍,代码基本上已经是最简了,基本上一句多余的代码都没有,其实代码并不难,基本上就是对多态的运用,如果不懂什么是多态,那你需要多看看java高级了,其实设计模式都不难,主要是思想,能不能对多态,继承,灵活运用.还有的抽象思想.