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

推广型网站开发网址企业网站的作用和意义

推广型网站开发网址,企业网站的作用和意义,极简网站模板,深圳网站排名怎么做行为型设计模式 行为型模式(Behavioral Patterns):这类模式主要关注对象之间的通信。它们 分别是: 职责链模式(Chain of Responsibility)命令模式(Command)解释器模式(…

行为型设计模式

行为型模式(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 List<Observer> 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 函数还可以叫作 attach,remove 函数还可以叫作 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 Map<String, List<Subscriber>> subscribers = new HashMap<>();/*** 订阅消息** @param eventType  事件类型* @param subscriber 订阅者*/public void subscribe(String eventType, Subscriber subscriber) {List<Subscriber> 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) {List<Subscriber> subs = subscribers.get(eventType);if (subs != null) {subs.remove(subscriber);}}/*** 发布事件消息** @param eventType* @param event*/public void publish(String eventType, String event) {List<Subscriber> 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 来实现一个简单的消息发布和订阅功能。

添加依赖项:

<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.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 List<SyncObserver> 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.wooajung.com/news/32726.html

相关文章:

  • 做网页跳转网站手机黄页怎么找
  • 高新门户网站专题建设百度关键词优化方法
  • 兰州正规seo整站优化宁波seo外包推广软件
  • 做网站中山电商如何从零做起
  • 西安做网站好的公司2022年可以打开的网址
  • 土木特网站建设嘉兴网站建设制作
  • 网站兼容手机代码网络销售公司经营范围
  • 自己做网站的意义sem优化怎么做
  • 做网站建设的电话销售百度手机seo软件
  • 伊犁做网站上海免费关键词排名优化
  • 教育培训网站源码河源seo
  • 昆山建设信息网站百度搜索指数排行
  • 网络规划与设计是什么专业谷歌seo推广培训班
  • 做jsp网站用哪些软件下载宁波百度seo排名优化
  • 武汉网站定制武汉网站建设
  • 泰州网站建设费用萧山区seo关键词排名
  • 黄岐做网站html网页制作软件有哪些
  • 高青云速网站建设重庆网站制作系统
  • 给人做网站挣钱吗品牌整合营销
  • 跨平台网站制作重庆seo网站
  • h5页面制作素材seo自己怎么做
  • 微信应用开发平台关键词优化有哪些作用
  • 网站建设项目公告不花钱网站推广
  • 廊坊网站建设冀icp备徐州网站设计
  • 长沙网站建设多少钱合肥百度网站排名优化
  • 课程设计报告 网站开发怎样在百度上免费建网站
  • 专业做俄语网站建设人工在线客服系统
  • 十大免费下载软件郑州seo优化外包
  • 合肥网站设计 goz网络营销分类
  • 专门做影评的网站seo优化网站词