行为型-观察者模式(Observer)
1,观察者模式
观察者模式是一种行为设计模式, 允许你定义一种订阅机制, 可在对象事件发生时通知多个 “观察” 该对象的其他对象。
又被称为
2,观察者模式角色
-
Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
-
ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
-
Observer:抽象观察者,是观察者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
-
ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。
3,观察者模式 Demo
1,抽象观察者
package com.demo.base.design_partten.observer; /** * 观察者 * */ public interface Observer { /* * 订阅内容,接收订阅内容 * */ public void attachMsg(String subject, String msg); }
2,抽象主题
package com.demo.base.design_partten.observer; /** * 主题 * @author admin * */ public interface Subject { /** * 添加观察者 * */ public void attach(Observer observer); /** * 发布消息 * */ public void notify(String msg); /** * 移除观察者 * */ public void detach(Observer observer); }
3,观察者实现
package com.demo.base.design_partten.observer; /** * 观察者实例 * */ public class ConcreteObserver implements Observer { String name; @Override public void attachMsg(String subject, String msg) { System.out.println(String.format("观察者:%s 收到 %s 发布的消息:%s", name, subject, msg)); //doSth... } public ConcreteObserver(){} public ConcreteObserver(String name){ this.name = name; } }
4,主题实现
package com.demo.base.design_partten.observer; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.Set; /** * 主题实现类 * */ public class ConcreteSubject implements Subject{ /** * 观察者集合 * */ private Set<Observer> events = new LinkedHashSet<>(); //主题名称 String name; @Override public void attach(Observer observer) { events.add(observer); } @Override public void notify(String msg) { for(Observer observer : events){ observer.attachMsg(name, msg); } } @Override public void detach(Observer observe) { events.remove(observe); } public ConcreteSubject(){} public ConcreteSubject(String name){ this.name = name; } }
5,业务类
package com.demo.base.design_partten.observer; /** * 观察者模式: * 1,观察者接口 * 定义订阅方法,用来接收发布的消息 * 2,观察者实现类 * 实现订阅方法,接收发布的消息 * 3,主题接口 subject * 定义了添加观察者,删除观察者,发布消息三个接口 * 4,主题实现类 ConcreteSubject * 内部持有一个观察者结合,实现发布消息接口,发布消息时候循环调用观察者订阅方法。 * 5,测试方法 * 观察者订阅主题,调用主题的 attach 方法。 * 主题发布消息,会通知所有观察者 * * */ public class MainTest { public static void main(String[] args) { ConcreteObserver c1 = new ConcreteObserver("小明"); ConcreteObserver c2 = new ConcreteObserver("小李"); ConcreteObserver c3 = new ConcreteObserver("小张"); ConcreteSubject bos = new ConcreteSubject("老板"); bos.attach(c1); bos.attach(c2); bos.attach(c3); bos.attach(c1); ConcreteSubject s = new ConcreteSubject("家长"); s.attach(c1); s.attach(c2); s.attach(c3); s.notify("啥时候回来啊"); bos.notify("国庆都给我加班!"); } }
4,发布-订阅模式
相比观察者模式多了订阅中心。
1,发布者
package com.demo.base.design_partten.observer.publish_subscrice; /** * 发布者 * @author * */ public class Publisher { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public Publisher(){} public Publisher(String name){ this.name = name; } }
2,订阅者
package com.demo.base.design_partten.observer.publish_subscrice; /** * 订阅者 * @author admin */ public class SubScriber { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public SubScriber(){} public SubScriber(String name){ this.name = name; } public void getMessage(Publisher publisher, String msg){ System.out.println(String.format( "订阅者:%s 收到 %s 发布的消息:%s!", name, publisher.getName(), msg) ); } }
3,订阅中心接口
package com.demo.base.design_partten.observer.publish_subscrice; /** * @author admin * 订阅中心 */ public interface PublisherCentral { //添加发布者-订阅者 public void addPublisher(Publisher publisher, SubScriber... subScriber); //删除发布者-订阅者 public void removePublisher(Publisher publisher, SubScriber ... subScribers); //发布消息 public void publishMsg(Publisher publisher, String msg); }
4,订阅中心实现
package com.demo.base.design_partten.observer.publish_subscrice; import java.util.*; /** * @author admin */ public class PublisherCentralImpl implements PublisherCentral { private Map<Publisher, Set<SubScriber>> set = new HashMap<>(); private String name; public PublisherCentralImpl(){} public PublisherCentralImpl(String name){ this.name = name; } @Override public void addPublisher(Publisher publisher, SubScriber... subScriber) { Set<SubScriber> s = set.get(publisher); if(s == null){ s = new LinkedHashSet<>(Arrays.asList(subScriber)); set.put(publisher, s); }else{ s.addAll(Arrays.asList(subScriber)); } } @Override public void removePublisher(Publisher publisher, SubScriber... subScribers) { Set<SubScriber> s = set.get(publisher); if(s == null){ return; }else{ s.removeAll(Arrays.asList(subScribers)); } } @Override public void publishMsg(Publisher publisher, String msg) { Set<SubScriber> s = set.get(publisher); System.out.println(String.format("%s 在 %s 发布了消息:%s", publisher.getName(), name, msg)); if(s != null){ for(SubScriber subScriber : s){ subScriber.getMessage(publisher, msg); } } } }
5,业务类
package com.demo.base.design_partten.observer.publish_subscrice; /** * @author 发布-订阅模式 */ public class MainTest { public static void main(String[] args) { //订阅中心 PublisherCentral publisherCentral = new PublisherCentralImpl("报社一"); Publisher p1 = new Publisher("大河网"); Publisher p2 = new Publisher("河南网"); Publisher p3 = new Publisher("东京网"); publisherCentral.addPublisher(p1, new SubScriber("张三"), new SubScriber("李四"), new SubScriber("王五")); publisherCentral.addPublisher(p2, new SubScriber("张三"), new SubScriber("小六")); publisherCentral.addPublisher(p3, new SubScriber("join")); publisherCentral.publishMsg(p1, "大河网最新报道!"); publisherCentral.publishMsg(p2, "今年还行!"); publisherCentral.publishMsg(p3, "bird language!"); } }
5. 使用场景
- Spring 中的事件机制,就是观察者模式的实现。
本文作者:Hi.PrimaryC
本文链接:https://www.cnblogs.com/cnff/p/17274692.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步