《设计模式》之观察者模式

mac2025-10-04  3

观察者模式

观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新

观察者模式就两种角色,一是观察者,二是被观察者( 主题 ),也可以认为是订阅者和发布者。

收通知的就是观察者。

如果观察者和被观察者这几个字已被混淆,可以用报纸发布订阅来套。客户是订阅报纸,收报纸的人( 收通知 ),所以客户就是观察者,那么报社就是被观察者了。

使用

/** * 抽象类 * @author aodeng-低调小熊猫 * @since 19-7-15 */ public abstract class Customer { /** * <p> * 定义一个抽象方法 * </p> * @author aodeng * @since 19-7-15 */ public abstract void update(); }

/** * 收到通知的观察者客户A * @author aodeng-低调小熊猫 * @since 19-7-15 */ public class CustomerA extends Customer { @Override public void update() { System.out.println("我是客户A,我收到报纸了!"); } }

/** * 收到通知的观察者客户B * @author aodeng-低调小熊猫 * @since 19-7-15 */ public class CustomerB extends Customer { @Override public void update() { System.out.println("我是客户B,我收到报纸了"); } }

/** * 被观察者 报社 * @author aodeng-低调小熊猫 * @since 19-7-15 */ public class NewsOffice { private List<Customer> customerList=new ArrayList<>(); public void add(Customer customer){ this.customerList.add(customer); } /** * <p> * 模拟新报纸来了 * </p> * @author aodeng * @since 19-7-15 */ public void newspaperCome(){ this.notifyAllObservers(); } public void notifyAllObservers(){ for (Customer customer : customerList) { customer.update(); } } }

测试

public static void main(String[] args) { System.out.println("Hello World!"); NewsOffice newsOffice=new NewsOffice(); newsOffice.add(new CustomerA()); newsOffice.add(new CustomerB()); newsOffice.newspaperCome(); } 输出: Hello World! 我是客户A,我收到报纸了! 我是客户B,我收到报纸了

加强

/** * 定义被观察者接口 * @author aodeng-低调小熊猫 * @since 19-7-15 */ public interface ISubject { public void registerObserver(Customer customer); public void removeObserver(Customer customer); public void notifyObservers(); } /**被观察者 报社 加强版 * @author aodeng-低调小熊猫 * @since 19-7-15 */ public class NewsOfficeNiu implements ISubject { private List<Customer> customerList = new ArrayList<>(); @Override public void registerObserver(Customer customer) { this.customerList.add(customer); } @Override public void removeObserver(Customer customer) { customerList.remove(customer); } @Override public void notifyObservers() { for (Customer customer : customerList) { customer.update(); } } //模拟报纸来了 public void newspaperCome(){ this.notifyObservers(); } }

测试

System.out.println("加强版========"); ISubject iSubject=new NewsOfficeNiu(); Customer customera=new CustomerA(); iSubject.registerObserver(customera); iSubject.removeObserver(customera); iSubject.registerObserver(new CustomerB()); ((NewsOfficeNiu) iSubject).newspaperCome(); 输出: 加强版======== 我是客户B,我收到报纸了

Java 提供的观察者模式

Java 已经为我们提供观察者模式所需要的类:Observer 类和 Subject 类,只不过在 Java 中 Subject 不叫 Subject,而叫 Observable。

copy 一个demo

//demo public class NewsOffice2 extends Observable { /** * 模拟报纸来了 */ public void newspaperCome(){ this.setChanged(); this.notifyObservers(); } } public class CustomerC implements Observer { @Override public void update(Observable o, Object arg) { System.out.println("我是客户C,我收到消息啦"); } } //测试 Observableoffice = new NewsOffice2(); Observer observer = new CustomerC(); office.addObserver(observer); ((NewsOffice2) office).newspaperCome();

总结

java自带的考虑到了线程安全,但是自己写的很多时候比较方便,有利有弊

1.优点观察者和被观察者之间抽象耦合,自有一套触发机制,被观察者无需知道通知对象是谁,只要是符合观察者接口的就可以。

2.缺点观察者只知道被观察者发生变化,而无法知道是如何发生变化的,比如是修改了 name 字段还是其他,观察者都不知道。如果有很多个观察者,一个个通知比较耗时。

源码

源码地址:https://github.com/java-aodeng/hope

Links:

CI/CD 流程以及原理说明 Github 个人博客:ilovey.live(新域名,爱生活) 熊猫哥星球基地 欢迎关注公众号【低调小熊猫】

本文由低调小熊猫一文多发操作发布! 欢迎关注公众号:低调小熊猫

最新回复(0)