观察者模式
是行为模式之一,作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象的状态。observer模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对象之间保持状态同步。
属于类和类之间的关系,不涉及到继承,观察者模式很好理解,类似于邮件订阅和RSS订阅,当我们浏览一些博客或wiki时,经常会看到RSS图标,就这的意思是,当你订阅了该文章,如果后续有更新,会及时通知你。其实,简单来讲就一句话:当一个对象变化时,其它依赖该对象的对象都会收到通知,并且随着变化!对象之间是一种一对多的关系。先来看看关系图:
我解释下这些类的作用:MySubject类就是我们的主对象,Observer1和Observer2是依赖于MySubject的对象,当MySubject变化时,Observer1和Observer2必然变化。AbstractSubject类中定义着需要监控的对象列表,可以对其进行修改:增加或删除被监控对象,且当MySubject变化时,负责通知在列表内存在的对象。
**********************************************************************************************************
角色:
Subject 被观察者,当需要被观察者状态发生变化时候,需要通知队列中所有观察者对象,Subject
需要维持(添加,删除,通知)一个观察者对象的队列列表
ConcreteSubject 被观察者对象的具体实现,包含一些基本属性状态和其他操作
Observer 观察者 接口或者抽象类,当Subject被观察者状态发生改变时候,Observer对象通过一个
callback回调函数得到通知
ConcreteObserver:观察者具体实现,得到通知后将完成一些具体业务逻辑处理。;
实例一:自己实现观察者和被观察者的代码
***********************************************************************
//观察者接口
public interface Observer {
public void update();
}
***********************************************************************
//观察者1
public class Observer1 implements Observer{
@Override
public void update() {
System.out.println("observer1 has received!");
}
}
***********************************************************************
//观察者2
public class Observer2 implements Observer {
@Override
public void update() {
System.out.println("observer2 has received!");
}
}
***********************************************************************
//定义了需要被监控的列表
public interface Subject {
/*增加观察者*/
public void add(Observer observer);
/*删除观察者*/
public void del(Observer observer);
/*通知所有的观察者*/
public void notifyObservers();
/*自身的操作*/
public void operation();
}
***********************************************************************
//
public class AbstractSubject implements Subject {
@Override
public void operation() {
}
private Vector<Observer> vector = new Vector<Observer>();
@Override
public void add(Observer observer) {
vector.add(observer);
}
@Override
public void del(Observer observer) {
vector.remove(observer);
}
@Override
public void notifyObservers() {
Enumeration<Observer> enumo = vector.elements();
while(enumo.hasMoreElements()){
enumo.nextElement().update();
}
}
}
***********************************************************************
public class MySubject extends AbstractSubject {
@Override
public void operation() {
System.out.println("update self!");
notifyObservers();
}
}
***********************************************************************
//测试
public class MainClass {
public static void main(String[] args) {
Subject sub = new MySubject();
sub.add(new Observer1());
sub.add(new Observer2());
sub.operation();
}
}
**************************************************
测试结果:
update self!
observer1 has received!
observer2 has received!
********************************************
实例二:通过继承java自带的observerable和实现Observer接口调用
/**
* 被观察对象
*/
public class Person extends Observable {
private String name;
private int age;
private String sex;
public Person() {
}
public Person(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
//当被观察者发送变化时候,唤醒观察者调用回调函数更新
this.setChanged();
this.notifyObservers();
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.setChanged();
this.notifyObservers();
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.setChanged();
this.notifyObservers();
this.sex = sex;
}
}
/**
* 观察者
*/
public class MyObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("观察者对象:对象发送改变!");
}
}
测试
/**
* 观察者模式Observer
*/
public class MainClass {
public static void main(String[] args) {
Person p = new Person();
//注册观察者
p.addObserver(new MyObserver());
int i = p.countObservers();
System.out.println(i+"个观察者");
p.setAge(18);
p.setName("蒸桑拿");
p.setSex("man");
System.out.println("---------------------");
Person person = new Person();
person.addObserver(new MyObserver());
person.setSex("男");
person.setName("lisi");
person.setAge(33);
}
}
测试结果
1个观察者
观察者对象:对象发送改变!
观察者对象:对象发送改变!
观察者对象:对象发送改变!
---------------------
观察者对象:对象发送改变!
观察者对象:对象发送改变!
观察者对象:对象发送改变!
************************************
实例三:
public class Article {
private String articleTitle;
private String articleContext;
public String getArticleTitle() {
return articleTitle;
}
public void setArticleTitle(String articleTitle) {
this.articleTitle = articleTitle;
}
public String getArticleContext() {
return articleContext;
}
public void setArticleContext(String articleContext) {
this.articleContext = articleContext;
}
@Override
public String toString() {
return "Article{" +
"articleTitle='" + articleTitle + '\'' +
", articleContext='" + articleContext + '\'' +
'}';
}
}
/**
*被观察者
*/
public class BlogUser extends Observable {
public void publishBlog(String articleTitle,String articleContext) {
Article article = new Article();
article.setArticleTitle(articleTitle);
article.setArticleContext(articleContext);
System.out.println("博客发表新文章了,文章标题:"+articleTitle+",文章内容"+articleContext);
this.setChanged();
//可以传递参数给观察者
this.notifyObservers(article);
}
}
/**
* 观察者
*/
public class MyObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
//这个observer参数是具体的被观察者,arg是被观察者传递过来的参数,是个Object类型
System.out.println(o);
System.out.println(arg);
System.out.println("博主发表新文章了,快去看吧!");
}
}
/**
* 发布订阅观察者和被观察者
*/
public class MainClass {
public static void main(String[] args) {
BlogUser blogUser = new BlogUser();
blogUser.addObserver(new MyObserver());
blogUser.publishBlog("java虚拟机","内容是java虚拟机,从认识到精通");
}
}
测试结果:
博客发表新文章了,文章标题:java虚拟机,文章内容内容是java虚拟机,从认识到精通
com.atguigu.observer.observerDemo2.BlogUser@135fbaa4
Article{articleTitle='java虚拟机', articleContext='内容是java虚拟机,从认识到精通'}
博主发表新文章了,快去看吧!
四、事例
自己实现观察者
被依赖方Subject
/**
* @auhtor
* @create 2023-02-09-13:43
* 1的一方
*/
public interface Subject {
void register(Observer observer);
void remove(Observer observer);
void notifyObjserver();
}
实际实现者被依赖方
/**
* @auhtor
* @create 2023-02-09-13:41
* 商店
*/
public class Shop implements Subject{
// 产品
private String product;
private List<Observer> observerList = new ArrayList<>();
public String getProduct() {
return product;
}
public Shop setProduct(String product) {
this.product = product;
notifyObjserver();
return this;
}
public List<Observer> getObserverList() {
return observerList;
}
public Shop setObserverList(List<Observer> observerList) {
this.observerList = observerList;
return this;
}
// 注册
@Override
public void register(Observer observer) {
observerList.add(observer);
}
// 注销
@Override
public void remove(Observer observer) {
observerList.remove(observer);
}
// 通知
@Override
public void notifyObjserver() {
if (observerList != null && observerList.size() > 0) {
observerList.stream().forEach(oberver->oberver.info());
}
}
}
依赖方抽象Observer
public interface Observer {
void info();
}
抽象Observer
public abstract class Buyer implements Observer{
protected String name;
protected Shop shop;
public String getName() {
return name;
}
public Buyer setName(String name) {
this.name = name;
return this;
}
public Shop getShop() {
return shop;
}
public Buyer setShop(Shop shop) {
this.shop = shop;
return this;
}
}
实际的依赖方
// 铁粉
public class PinkBuyer extends Buyer{
@Override
public void info() {
if(super.shop.getProduct().contains("水果手机")){
System.out.println(super.name + "购买" + shop.getProduct());
}
}
}
// 剁手党
public class HandChopper extends Buyer{
@Override
public void info() {
System.out.println(super.name + "购买" + shop.getProduct());
}
}
测试打印输出
public class MainClient {
public static void main(String[] args) {
// 观察者模式:1对多的 被动变为主动 两个对象相互持有引用,方便通知和获取信息
Shop shop = new Shop();
PinkBuyer pinkBuyer = new PinkBuyer();
pinkBuyer.setName("铁粉");
pinkBuyer.setShop(shop);
HandChopper handChopper = new HandChopper();
handChopper.setName("剁手党");
handChopper.setShop(shop);
shop.register(pinkBuyer);
shop.register(handChopper);
shop.setProduct("水果手机");
}
}
// console
铁粉购买水果手机
剁手党购买水果手机