当前位置: 首页 > news >正文

南宁网站设计和开发大赛二级域名免费申请

南宁网站设计和开发大赛,二级域名免费申请,舟山建设技术学校网站,简单网页编辑软件行为型设计模式 行为型模式#xff08;Behavioral Patterns#xff09;#xff1a;这类模式主要关注对象之间的通信。它们 分别是#xff1a; 职责链模式#xff08;Chain of Responsibility#xff09;命令模式#xff08;Command#xff09;解释器模式#xff08;…行为型设计模式 行为型模式Behavioral Patterns这类模式主要关注对象之间的通信。它们 分别是 职责链模式Chain of Responsibility命令模式Command解释器模式Interpreter迭代器模式Iterator中介者模式Mediator备忘录模式Memento观察者模式Observer状态模式State策略模式Strategy模板方法模式Template Method访问者模式Visitor 1. 观察者设计模式 1.1 概述 观察者模式是一种行为设计模式允许对象间存在一对多的依赖关系当一个对象的状态发生改变时所有依赖它的对象都会得到通知并自动更新。在这种模式中发生状态改变的对象被称为“主题”Subject依赖它的对象被称为“观察者”Observer。所以观察者模式Observer Design Pattern也被称为发布订阅模式Publish-Subscribe Design Pattern。 被依赖的对象叫作被观察者Observable依赖的对象叫作观察者Observer。在实际的项目开发中这两种对象的称呼是比较灵活的有各种不同的叫法比如Subject-Observer、Publisher-Subscriber、Producer-Consumer等等。不管怎么称呼只要应用场景符合刚刚给出的定义都可以看作是观察者模式。 我们通过一个例子来实现观察者模式。假设我们有一个气象站WeatherStation需要向许多不同的显示设备如手机App、网站、电子屏幕等提供实时天气数据。 首先我们需要创建一个Subject接口表示被观察的主题 /*** 接口描述被观察者应该提供注册、删除、通知观察者的能力** Author crysw* Version 1.0* Date 2024/1/1 21:43*/ public interface Subject {/*** 注册观察者** param observer*/void registerObserver(Observer observer);/*** 删除观察者** param observer*/void removeObserver(Observer observer);/*** 通知观察者*/void notifyObservers(); }接下来我们创建一个Observer接口表示依赖主题的观察者接口 /*** 接口描述观察者接口** Author crysw* Version 1.0* Date 2024/1/1 21:50*/ public interface Observer {/*** 更新新的天气气温** param temperature*/void update(float temperature); }创建一个具体的主题如WeatherStation实现Subject接口 /*** 类描述气象站被观察者** Author crysw* Version 1.0* Date 2024/1/1 21:49*/ public class WeatherStation implements Subject {// 温度private float temperature;// 所有依赖的观察者private ListObserver observers new ArrayList();// 修改温度public void changeTemperature(float temperature) {this.temperature temperature;// 通知所有观察者更新温度notifyObservers();}Overridepublic void registerObserver(Observer observer) {observers.add(observer);}Overridepublic void removeObserver(Observer observer) {observers.remove(observer);}Overridepublic void notifyObservers() {// 通知所有观察者更新温度for (Observer observer : observers) {observer.update(temperature);}} }最后我们创建具体的观察者并实现Observer接口如AppClient、WebClient /*** 类描述手机客户端** Author crysw* Version 1.0* Date 2024/1/1 21:55*/ Slf4j public class AppClient implements Observer {Overridepublic void update(float temperature) {log.info(app更新了温度现在的温度是: {}, temperature);} }/*** 类描述网页客户端** Author crysw* Version 1.0* Date 2024/1/1 21:57*/ Slf4j public class WebClient implements Observer {Overridepublic void update(float temperature) {log.info(网页客户端更新了气温温度是{}, temperature);} }测试用例 /*** 类描述观察者设计模式测试案例** Author crysw* Version 1.0* Date 2024/1/1 21:57*/ public class ObserverTest {Testpublic void test() {// 定义气象站主题-被观察者WeatherStation weatherStation new WeatherStation();// 定义观察者客户端观察者Observer appClient new AppClient();Observer webClient new WebClient();// 注册观察者weatherStation.registerObserver(appClient);weatherStation.registerObserver(webClient);// 更新温度weatherStation.changeTemperature(20.05f);} }测试结果 [main] INFO cn.itcast.designPatterns.observer.weather.AppClient - app更新了温度现在的温度是: 20.05 [main] INFO cn.itcast.designPatterns.observer.weather.WebClient - 网页客户端更新了气温温度是20.05使用观察者模式的优点 观察者和主题之间的解耦主题只需要知道观察者实现了Observer接口而无需了解具体的实现细节。提高代码的可维护性和可扩展性。可以动态添加和删除观察者通过调用registerObserver和removeObserver方法可以在运行时添加和删除观察者。主题和观察者之间的通信是自动的当主题的状态发生变化时观察者会自动得到通知并更新自己的状态。 上面的小例子算是观察者模式的“模板代码”可以反映该模式大体的设计思路。在真实的软件开发中并不需要照搬上面的模板代码。观察者模式的实现方法各式各样函数、类的命名等会根据业务场景的不同有很大的差别比如 register 函数还可以叫作 attachremove 函数还可以叫作 detach 等等。不过万变不离其宗设计思路都是差不多的。 了解了观察者设计模式的基本使用方式我们接下来看看他的具体使用场景。 1.2 使用场景 以下是一些使用观察者设计模式的例子 股票行情应用股票价格更新可以作为被观察者投资者可以作为观察者。当股票价格发生变化时所有订阅了该股票的投资者都会收到通知并更新自己的投资策略。 网络聊天室聊天室服务器可以作为被观察者用户可以作为察者。当有新消息时聊天室服务器会通知所有在线用户更新聊天记录。 拍卖系统拍卖系统可以作为被观察者用户可以作为观察者。当出价发生变化时所有关注该拍品的用户都会收到通知并更新自己的出价策略。 订阅系统内容发布可以作为被观察者用户可以作为观察者。当有新内容发布时所有订阅了该内容的用户都会收到通知并获取最新内容。 电子邮件通知系统任务状态更新可以作为被观察者相关人员可以作为观察者。当任务状态发生变化时所有关注该任务的人员都会收到通知并查看任务详情。 社交网络被关注的用户可以作为被观察者关注者可以作为观察者。当被关注的用户发布新动态时所有关注者都会收到通知并查看动态。 1.3 发布订阅 发布-订阅模式和观察者模式都是用于实现对象间的松耦合通信的设计模式。尽管它们具有相似之处但它们在实现方式和使用场景上存在一些关键区别。他们在概念上有一定的相似性都是用于实现对象间的松耦合通信。可以将发布-订阅模式看作是观察者模式的一种变体或扩展。 观察者模式定义了一种一对多的依赖关系当一个对象被观察者的状态发生变化时所有依赖于它的对象观察者都会得到通知并自动更新。在这个模式中被观察者和观察者之间存在直接的关联关系。观察者模式主要包括两类对象被观察者Subject和观察者Observer。 发布-订阅模式生产者和消费者引入了第三方组件通常称为消息代理或事件总线该组件负责维护发布者和订阅者之间的关系。这意味着发布者和订阅者彼此不直接通信而是通过消息代理进行通信。这种间接通信允许发布者和订阅者在运行时动态地添加或删除从而提高了系统的灵活性和可扩展性。 Java中的发布-订阅模式示例 // 订阅者接口 public interface Subscriber {/*** 接收事件通知** param event*/void onEvent(String event); }// 具体的订阅者 Slf4j public class ConcreteSubscriber implements Subscriber {Overridepublic void onEvent(String event) {log.info(ConcreteSubscriber收到事件: {}, event);} }// 具体的订阅者2 Slf4j public class ConcreteSubscriber2 implements Subscriber {Overridepublic void onEvent(String event) {log.info(ConcreteSubscriber2收到事件: {}, event);} }订阅者与事件发布之间通过消息总线代理来联系. /*** 类描述消息总线(代理实现主题事件发布注册订阅者删除订阅者等** Author crysw* Version 1.0* Date 2024/1/3 22:17*/ public class EventBus {// 使用一个map维护消息类型和该消息的订阅者private MapString, ListSubscriber subscribers new HashMap();/*** 订阅消息** param eventType 事件类型* param subscriber 订阅者*/public void subscribe(String eventType, Subscriber subscriber) {ListSubscriber subs subscribers.get(eventType);if (subs null) {subs new ArrayList();}subs.add(subscriber);subscribers.put(eventType, subs);}/*** 删除订阅** param eventType* param subscriber*/public void unSubscribe(String eventType, Subscriber subscriber) {ListSubscriber subs subscribers.get(eventType);if (subs ! null) {subs.remove(subscriber);}}/*** 发布事件消息** param eventType* param event*/public void publish(String eventType, String event) {ListSubscriber subs subscribers.get(eventType);if (subs ! null) {for (Subscriber sub : subs) {sub.onEvent(event);}}} }发布订阅的测试案例 Test public void test2() {// 创建消息代理EventBus eventBus new EventBus();// 创建订阅者Subscriber subscriber new ConcreteSubscriber();Subscriber subscriber2 new ConcreteSubscriber2();// 订阅事件String eventType eventA;eventBus.subscribe(eventType, subscriber);eventBus.subscribe(eventType, subscriber2);// 发布事件eventBus.publish(eventType, 这是事件A发布的消息);log.info();// 取消订阅eventBus.unSubscribe(eventType, subscriber2);// 再次发布事件eventBus.publish(eventType, 事件A又来发布的消息again);}测试结果 [main] INFO cn.itcast.designPatterns.observer.subscriber.ConcreteSubscriber - ConcreteSubscriber收到事件: 这是事件A发布的消息 [main] INFO cn.itcast.designPatterns.observer.subscriber.ConcreteSubscriber2 - ConcreteSubscriber2收到事件: 这是事件A发布的消息 [main] INFO cn.itcast.designPattern.ObserverTest - [main] INFO cn.itcast.designPatterns.observer.subscriber.ConcreteSubscriber - ConcreteSubscriber收到事件: 事件A又来发布的消息again总结一下两者的区别 通信方式观察者模式中观察者与被观察者之间存在直接的关联关系而发布-订阅模式中发布者和订阅者通过一个第三方组件消息代理或事件总线进行通信彼此之间不存在直接关联关系。系统复杂性发布-订阅模式引入了一个额外的组件消息代理或事件总线增加了系统的复杂性但同时也提高了系统的灵活性和可扩展性。使用场景观察者模式适用于需要将状态变化通知给其他对象的情况而发布-订阅模式适用于事件驱动的系统尤其是那些需要跨越多个模块或组件进行通信的场景。 发布-订阅模式的优点 解耦在发布-订阅模式中发布者和订阅者之间没有直接关联它们通过一个中间组件消息代理或事件总线进行通信。这种间接通信可以使发布者和订阅者在运行时动态地添加或删除从而进一步降低了它们之间的耦合度。 可扩展性发布-订阅模式更容易向系统中添加新的发布者和订阅者而无需修改现有的代码。这使得系统在不同组件之间通信时具有更好的可扩展性。 模块化由于发布者和订阅者之间的通信通过中间组件进行可以将系统划分为更小、更独立的模块。这有助于提高代码的可维护性和可读性。 异步通信发布-订阅模式通常支持异步消息传递这意味着发布者和订阅者可以在不同的线程或进程中运行。这有助于提高系统的并发性能和响应能力。 消息过滤在发布-订阅模式中可以利用中间组件对消息进行过滤使得订阅者只接收到感兴趣的消息。这可以提高系统的性能减少不必要的通信开销。 发布-订阅模式也有一些缺点例如增加了系统的复杂性因为引入了额外的中间组件。根据具体的应用场景和需求来选择合适的设计模式。 1.4 源码使用 1.4.1 jdk中的观察者 java.util.Observable类实现了主题Subject的功能而java.util.Observer接口则定义了观察者Observer的方法。 通过调用Observable对象的notifyObservers()方法可以通知所有注册的Observer对象让它们更新自己的状态。 案例假设有一个银行账户类它的余额是可变的。当余额发生变化时需要通知所有的观察者比如说银行客户以便它们更新自己的显示信息。 使用观察者模式来实现银行客户对自己账户余额的实时监控。 首先创建主题类实现存款取款获取余额注册订阅者删除订阅者等 package cn.itcast.designPatterns.observer.jdkimpl;import java.util.Observable;/*** 类描述银行账户类实现Observable类** Author crysw* Version 1.0* Date 2024/1/9 21:37*/ public class BankAccount extends Observable {/*** 余额*/private double balance;public BankAccount(double balance) {this.balance balance;}/*** 获取当前余额** return*/public double getBalance() {return balance;}/*** 存款操作** param amount*/public void deposit(double amount) {balance amount;// 继承下来的方法表示状态发生改变setChanged();// 继承下来的方法通知所有观察者notifyObservers();}/*** 取款操作** param amount*/public void withdraw(double amount) {balance - amount;setChanged();notifyObservers();} }再创建观察者类, 订阅者 /*** 类描述银行客户1-观察者** Author crysw* Version 1.0* Date 2024/1/9 21:45*/ Slf4j public class ClientOberver implements Observer {Overridepublic void update(Observable observable, Object arg) {log.info(客户1查看余额已更新为: {}, ((BankAccount) observable).getBalance());} }/*** 类描述银行客户2-观察者** Author crysw* Version 1.0* Date 2024/1/9 21:45*/ Slf4j public class ClientOberver2 implements Observer {Overridepublic void update(Observable observable, Object arg) {log.info(客户2查看余额已更新为: {}, ((BankAccount) observable).getBalance());} }测试用例 /*** 测试jdk中观察者模式的实现*/ Test public void test3() {// 创建发布事件主题对象BankAccount bankAccount new BankAccount(100.00);log.info(银行账户余额是{}, bankAccount.getBalance());// 创建订阅者ClientOberver clientOberver new ClientOberver();ClientOberver2 clientOberver2 new ClientOberver2();// 注册订阅者bankAccount.addObserver(clientOberver);bankAccount.addObserver(clientOberver2);// 存款50bankAccount.deposit(50.00);log.info();// 取款25bankAccount.withdraw(25.00);log.info();// 删除订阅者bankAccount.deleteObserver(clientOberver2);log.info();// 取款20bankAccount.withdraw(20.00); }测试结果 [main] INFO cn.itcast.designPattern.ObserverTest - 银行账户余额是100.0 [main] INFO cn.itcast.designPatterns.observer.jdkimpl.ClientOberver2 - 客户2查看余额已更新为: 150.0 [main] INFO cn.itcast.designPatterns.observer.jdkimpl.ClientOberver - 客户1查看余额已更新为: 150.0 [main] INFO cn.itcast.designPattern.ObserverTest - [main] INFO cn.itcast.designPatterns.observer.jdkimpl.ClientOberver2 - 客户2查看余额已更新为: 125.0 [main] INFO cn.itcast.designPatterns.observer.jdkimpl.ClientOberver - 客户1查看余额已更新为: 125.0 [main] INFO cn.itcast.designPattern.ObserverTest - [main] INFO cn.itcast.designPattern.ObserverTest - [main] INFO cn.itcast.designPatterns.observer.jdkimpl.ClientOberver - 客户1查看余额已更新为: 105.0这个案例中BankAccount类继承了java.util.Observable类表示它是一个主题Subject。在存款或取款操作时它会调用setChanged()方法表示状态已经改变并调用notifyObservers()方法通知所有观察者Observer。 两个观察者clientOberver和clientOberver2它们分别实现了Observer接口的update()方法。当观察者收到更新通知时它们会执行自己的业务逻辑比如更新显示信息。 1.4.2 Guava中的消息总线 Guava 库中的 EventBus 类提供了一个简单的消息总线实现可以帮助您在 Java应用程序中实现发布-订阅模式。以下是一个简单的示例演示了如何使用 Guava 的EventBus 来实现一个简单的消息发布和订阅功能。 添加依赖项 dependencygroupIdcom.google.guava/groupIdartifactIdguava/artifactIdversion30.1-jre/version /dependency定义一个事件消息类 /*** 类描述事件消息类** Author crysw* Version 1.0* Date 2024/1/9 22:02*/ public class MessageEvent {private String message;public MessageEvent(String message) {this.message message;}public String getMessage() {return message;} }创建一个订阅者类。在订阅者类中定义一个方法并使用 Subscribe 注解标记该方法以便 EventBus 能够识别该方法作为事件处理器 /*** 类描述订阅者类** Author crysw* Version 1.0* Date 2024/1/9 22:03*/ Slf4j public class MessageSubscriber {Subscribepublic void handleMessageEvent(MessageEvent event) {log.info(收到消息: {}, event.getMessage());} }测试用例 /*** 测试guava的发布订阅实现*/ Test public void test4() {// 创建 EventBus 事件实例com.google.common.eventbus.EventBus eventBus new com.google.common.eventbus.EventBus();// 创建并注册订阅者MessageSubscriber messageSubscriber new MessageSubscriber();eventBus.register(messageSubscriber);// 发布事件eventBus.post(new MessageEvent(Hello, EventBus!));// 删除订阅者eventBus.unregister(messageSubscriber);// 再次发布事件此时订阅者已取消注册将不会收到消息eventBus.post(new MessageEvent(Another message)); }在这个示例中我们创建了一个 EventBus 实例然后创建并注册了一个MessageSubscriber 类型的订阅者。当我们使用 eventBus.post() 方法发布一个 MessageEvent 事件时订阅者的 handleMessageEvent 方法将被调用并输出收到的消息。 注意如果订阅者处理事件的方法抛出异常 EventBus 默认情况下不会对异常进行处理。如果需要处理异常可以在创建 EventBus 实例时传入一个自定义的SubscriberExceptionHandler。 public class EventBus {public EventBus(SubscriberExceptionHandler exceptionHandler) {this(default, MoreExecutors.directExecutor(), Dispatcher.perThreadDispatchQueue(), exceptionHandler);} } public interface SubscriberExceptionHandler {void handleException(Throwable var1, SubscriberExceptionContext var2); }1.5 进阶 之前讲到的实现方式是一种同步阻塞的实现方式。观察者和被观察者代码在同一个线程内执行被观察者一直阻塞直到所有的观察者代码都执行完成之后才执行后续的代码。 如果注册接口是一个调用比较频繁的接口对性能非常敏感希望接口的响应时间尽可能短那我们可以将同步阻塞的实现方式改为异步非阻塞的实现方式以此来减少响应时间。 1.5.1 异步非阻塞模型 创建主题接口及实现 /*** 接口描述主题类发布事件等** Author crysw* Version 1.0* Date 2024/1/10 21:35*/ public interface SyncObservable {/*** 注册观察者** param observer*/void addObserver(SyncObserver observer);/*** 移除观察者** param observer*/void removeObserver(SyncObserver observer);/*** 通知观察者** param message*/void notifyObservers(String message); }/*** 类描述具体的主题实现类异步通知观察者** Author crysw* Version 1.0* Date 2024/1/10 21:37*/ public class SyncObservableImpl implements SyncObservable {private ListSyncObserver observers;private ExecutorService executorService;public SyncObservableImpl() {observers new ArrayList();executorService Executors.newCachedThreadPool();}/*** 消息更新后通知所有观察者** param message*/public void setMessage(String message) {notifyObservers(message);}Overridepublic void addObserver(SyncObserver observer) {observers.add(observer);}Overridepublic void removeObserver(SyncObserver observer) {observers.remove(observer);}Overridepublic void notifyObservers(String message) {for (SyncObserver observer : observers) {// 异步执行executorService.submit(() - observer.update(message));}} }创建观察者接口及实现 /*** 接口描述观察者接口** Author crysw* Version 1.0* Date 2024/1/10 21:34*/ public interface SyncObserver {void update(String message); }/*** 类描述** Author crysw* Version 1.0* Date 2024/1/10 21:36*/ Slf4j public class SyncObserverImpl implements SyncObserver {private String name;public SyncObserverImpl(String name) {this.name name;}Overridepublic void update(String message) {log.info({} received message: {}, name, message);} }测试用例 /*** 测试异步通知*/ Test public void test5() {// 创建主题发布事件对象SyncObservableImpl observable new SyncObservableImpl();// 创建观察者SyncObserver observer new SyncObserverImpl(crysw);SyncObserver observer2 new SyncObserverImpl(paanda);// 注册观察者observable.addObserver(observer);observable.addObserver(observer2);// 发布消息observable.setMessage(放假了放假了);// 移除观察者observable.removeObserver(observer);// 再次更新消息observable.setMessage(错了继续搬砖); }1.5.2 跨进程通信 不管是同步阻塞实现方式还是异步非阻塞实现方式都是进程内的实现方式。如果用户注册成功之后需要发送用户信息给大数据征信系统而大数据征信系统是一个独立的系统跟它之间的交互是跨不同进程的那如何实现一个跨进程的观察者模式呢 如果大数据征信系统提供了发送用户注册信息的 RPC 接口我们仍然可以沿用之前的实现思路在 notifyObservers() 函数中调用 RPC 接口来发送数据。但是我们还有更加常用的一种实现方式那就是基于消息队列Message Queue来实现。 当然这种实现方式也有弊端需要引入一个新的系统消息队列增加了维护成本。不过它的好处也非常明显。在原来的实现方式中观察者需要注册到被观察者中被观察者需要依次遍历观察者来发送消息。而基于消息队列的实现方式被观察者和观察者解耦更加彻底两部分的耦合更小。被观察者完全不感知观察者同理观察者也完全不感知被观察者。被观察者只管发送消息到消息队列观察者只管从消息队列中读取消息来执行相应的逻辑。
http://www.hkea.cn/news/14502652/

相关文章:

  • 推广效果最好的平台从零开始做网站seo
  • 罗湖商城网站设计公司建站教程视频下载
  • 广东电商网站建设wordpress微信朋友圈
  • 网站维护的主要内容福州专业网站开发很专业
  • jsp如何做网站界面外贸网站 seo
  • 搭建网站的价格代理网络游戏
  • 做商城网站外包好的设计网站
  • 沈阳网站seo公司wordpress能做外贸网站
  • 稀奇古怪好玩有用的网站网站pv多少可以
  • 制作什么网站好舟山网站制作公司
  • 深圳专业网站建设公司哪家好个旧市城乡建设局网站
  • 免费软件下载官方网站wordpress评论定制
  • 余姚网站建设服务常州网站制作公司有哪些
  • 苏州网站排名优化报价合肥网站建设方案
  • 工会网站建设比较好的工会怎么用网站做word文件
  • 网站建设方案书内容wordpress管理系统
  • 网站停留时间商城app官方下载
  • 网站流量利用手机网站 wap
  • 加盟网网站建设策划书二手物品交易网站设计英文
  • wordpress 建购物网站个人建设图片分享网站
  • 如何修改网站备案信息joomla 网站建设
  • iis配置网站是什么网络推广渠道分类
  • 太平洋在线企业网站管理系统品牌设计图片
  • 私人定制广州seo关键词优化是什么
  • 福建国通星驿网络科技有限公司北京百度seo推广
  • 苏州园区两学一做网站东坑镇做网站
  • 自助建站的优势紧急域名升级更换通知
  • 站长平台怎么做网站2018淘宝客网站开发
  • 西斗门的网站建设成都室内设计公司排名前十
  • 山西省建设厅政务中心网站互联网精准营销