优惠活动制作网站,php网站开发培训,手机摄影网站首页,wordpress 首页 动观察者模式 目录 观察者模式1、什么是观察者模式#xff1f;2、观察者模式优缺点及注意事项#xff1f;3、观察者模式实现#xff1f;4、手写线程安全的观察者模式#xff1f; 1、什么是观察者模式#xff1f; - 实例#xff1a;现实生活中很多事物都是依赖存在的#x…观察者模式 目录 观察者模式1、什么是观察者模式2、观察者模式优缺点及注意事项3、观察者模式实现4、手写线程安全的观察者模式 1、什么是观察者模式 - 实例现实生活中很多事物都是依赖存在的一个发生变化会影响很多事物。比如油价上涨关系很多企业很多家庭红绿灯发生变化时人们会停止会前进等。 - 观察者模式 (Observer Pattern) 是一种一对多的依赖关系让多个观察对象同时监听某一个主题对象当主题对象的状态发生变化时会自动通知所有观察者使得它们能够自动更新自己。适用于当一个对象的状态发生改变时所有依赖于它的对象都需要得到通知的情况。 - 观察者模式具体的角色 实现观察者模式时要注意具体目标对象和具体观察者对象之间不能直接调用否则将使两者之间紧密耦合起来这违反了面向对象的设计原则。 抽象主题Subject角色也叫抽象目标类它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法以及通知所有观察者的抽象方法。具体主题Concrete Subject角色也叫具体目标类它实现抽象目标中的通知方法当具体主题的内部状态发生改变时通知所有注册过的观察者对象。继承Subject类在这里实现具体业务在具体项目中该类会有很多变种。抽象观察者Observer角色它是一个抽象类或接口它包含了一个更新自己的抽象方法当接到具体主题的更改通知时被调用。具体观察者Concrete Observer角色实现抽象观察者中定义的抽象方法以便在得到目标的更改通知时更新自身的状态。 2、观察者模式优缺点及注意事项
- 优点 1.降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系.符合依赖倒置原则 2.目标与观察者之间建立了一套触发机制 - 缺点 1.目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用 2.当观察者对象很多时通知的发布会花费很多时间影响程序的效率 - 注意事项 1.JDK8 中java.util.Observable 类和 java.util.Observer 接口定义了观察者模式后面版本舍弃了因为在使用异步处理的情况下线程不安全。 2.要注意循环调用情况避免死锁。 3.可以去观察消息队列实现典型的观察者模式实现。
3、观察者模式实现
模仿jdk8中 Observable 类 和 Observer接口实现 - 目标类
public class Subject {private VectorObserver obs new Vector();public void addObserver(Observer o) {if (o null)throw new NullPointerException();if (!obs.contains(o)) {obs.add(o);}}public void deleteObserver(Observer o) {obs.remove(o);}public void notifyObservers() {for(Observer observer : this.obs) {observer.resopnse();}}
}- 具体实现目标类
public class ConcreteSubject extends Subject{// 具体实现public void doSomethings(){// 一些其它逻辑处理System.out.println(-----被观察者发生了改变------);super.notifyObservers();}
}- 观察者类
public interface Observer {// 响应void resopnse();
}- 具体观察者类
public class ConcreteObserver implements Observer{private int num;public ConcreteObserver(int num) {this.num num;}Overridepublic void resopnse() {System.out.println(观察者num做出改变);}
}- 执行任务
public class Main {public static void main(String[] args) {
// --------------- 观察者模式 -----------------// 先创建多个观察者ConcreteSubject concreteSubject new ConcreteSubject();for (int a 0; a 10; a) {concreteSubject.addObserver(new ConcreteObserver(a1));}concreteSubject.doSomethings();}4、手写线程安全的观察者模式 设定场景手机花费快没钱了运营商通知你要缴费了。 这里运营商就是被观察者用户就是观察者用户的手机号就是注册的一个过程运营商通知用户。 使用jdk中com.util.concurrent提供的线程安全的类CountDownLatchCountDownLatch就一个线程同步工具它相当于一个倒序计数器用来协调多个线程的执行。多个线程通过调用它们所共享的计数器CountDownLatch的countDown方法来让计数器减1。通过await方法来阻塞当前线程直到计数器变成0。达到线程阻塞直至其他线程执行完成被重新唤醒。主要有三个方法 1.构造函数初始化state的值state等于同步线程数 2.await()让线程阻塞 3.countDown()计数器(state)减1的方法。 public class Main {public static void main(String[] args) {// --------------- 安全的观察者模式 --------------// 设定场景手机花费快没钱了运营商通知你要缴费了。 这里运营商就是被观察者用户就是观察者用户的手机号就是注册的一个过程运营商通知用户。ConcreteTelecomOperator telecomOperator new ConcreteTelecomOperator(中国电信);telecomOperator.addUser(new ConcreteUser(张三));telecomOperator.addUser(new ConcreteUser(李四));telecomOperator.addUser(new ConcreteUser(王五));telecomOperator.addUser(new ConcreteUser(小明));telecomOperator.doSomeThing(通知您您已欠费请及时缴费。祝你生活愉快);}
}/*** program: practice_tools* description: 运营商目标类* author: tiezhu* create: 2025-01-20 09:58**/
public class TelecomOperator {private String name;private ConcurrentMapString, User obs;public TelecomOperator(String name) {this.name name;obs new ConcurrentHashMap();}public void addUser(User u){if (u null)throw new NullPointerException();if (!obs.containsKey(u.getName())) {obs.put(u.getName(),u);}}public void removeUser(User u){obs.remove(u.getName());}public void notifyObservers(String content) {try {long beginTime System.currentTimeMillis();CountDownLatch latch new CountDownLatch(obs.size());for (User user : obs.values()) {user.response(content);latch.countDown();}latch.await();long endTime System.currentTimeMillis();System.out.println(name 消息发送完毕耗时 (endTime - beginTime));System.out.println();} catch (InterruptedException e) {e.printStackTrace();}}
}
/*** program: practice_tools* description: 具体目标类* author: tiezhu* create: 2025-01-20 11:43**/
public class ConcreteTelecomOperator extends TelecomOperator{public ConcreteTelecomOperator(String name) {super(name);}public void doSomeThing(String content){System.out.println(开始发布信息);super.notifyObservers(content);}
}/*** 用户观察者*/
public interface User {void response(String content);String getName();
}/*** program: practice_tools* description: 观察者实体类* author: tiezhu* create: 2025-01-20 10:04**/
public class ConcreteUser implements User{private String name;public ConcreteUser(String name) {this.name name;}Overridepublic void response(String content) {System.out.println(接收到了消息为content);System.out.println(name 准备去缴费了);}Overridepublic String getName() {return name;}
}
结果执行结果和创建顺序不同不用按照创建顺序执行完再执行了。