`

设计模式之观察者模式

阅读更多

 今天放假,又有时间继续啃《java设计模式》这本书了。每次学会一种设计模式内心都会有一种小小的成就感,但是懂是懂了,不知道会不会用。主要是现在没有什么项目经验,设计模式学了也派不上用场。不管怎样,学了总比没学好,以后总会派上用场的。

  首先,何为观察者模式?观察者模式是关于多个对象想知道一个对象中数据的变化的情况一种模式。比如说现在几乎所有的高校附近都会有大学生兼职中心,也就是兼职中介吧(大一大二的时候还去过,加会员还交了100大洋呢。),兼职中心每天都会把兼职信息通知给所有的会员。这就是一个观察者模式,这里会员也就是观察者,兼职中心就是被观察者,也称作主题。

  观察者模式结构中包括四种角色:

  一、主题:主题是一个接口,该接口规定了具体主题需要实现的方法,比如添加、删除观察者以及通知观察者更新数据的方法。

  二、观察者:观察者也是一个接口,该接口规定了具体观察者用来更新数据的方法。

  三、具体主题:具体主题是一个实现主题接口的类,该类包含了会经常发生变化的数据。而且还有一个集合,该集合存放的是观察者的引用。

  四:具体观察者:具体观察者是实现了观察者接口的一个类。具体观察者包含有可以存放具体主题引用的主题接口变量,以便具体观察者让具体主题将自己的引用添加到具体主题的集合中,让自己成为它的观察者,或者让这个具体主题将自己从具体主题的集合中删除,使自己不在时它的观察者。

  在上面的兼职中心的例子中,兼职中心就是一个具体主题,它可以更新各种兼职信息,并且通知给它的会员,当然还可以增加会员和删除会员。会员就是一个观察者,它关注着兼职中心的信息,能够及时收到兼职中心更新过来的信息。

  代码如下:

  1.主题

复制代码
1 package com.observer;
2 
3 public interface Subject {
4     void addObserver(Observer o);
5     void deleteObserver(Observer o);
6     void notifyObservers();
7 }
复制代码

  2.具体主题

复制代码
 1 package com.observer;
 2 
 3 import java.util.ArrayList;
 4 
 5 public class SeekJobCenter implements Subject {
 6     String mess;
 7     boolean changed;
 8     ArrayList<Observer> personList;
 9     public SeekJobCenter() {
10         personList = new ArrayList<Observer>();
11         mess = "";
12         changed = false;
13     }
14     //添加求职者
15     public void addObserver(Observer o) {
16         if(!(personList.contains(o))){
17             personList.add(o);
18         }
19     }
20     //删除求职者
21     public void deleteObserver(Observer o) {
22         if(personList.contains(o)){
23             personList.remove(o);
24         }
25     }
26     //通知所有求职者
27     public void notifyObservers() {
28         if(changed){
29             for (int i = 0; i < personList.size(); i++) {
30                 Observer o = personList.get(i);
31                 o.hearTelephone(mess);
32             }
33             changed = false;
34         }
35     }
36     //刷新信息
37     public void giveNewMess(String str){
38         if(str.equals(mess)){
39             changed = false;
40         }else{
41             mess = str;
42             changed = true;
43         }
44     }
45 
46 }
复制代码

  3.观察者

1 package com.observer;
2 
3 public interface Observer {
4     public void hearTelephone(String mess);
5 }

  4.具体观察者

  在该例子中,具体观察者有两个,一个关注兼职中心的所有信息,另一个只关注“促销员”和“发单员”的兼职信息。

  UniversityStudent.java

复制代码
 1 package com.observer;
 2 
 3 import java.io.File;
 4 import java.io.FileNotFoundException;
 5 import java.io.IOException;
 6 import java.io.RandomAccessFile;
 7 
 8 public class UniversityStudent implements Observer{
 9     Subject subject;
10     File myFile;
11     public UniversityStudent(Subject subject,String fileName) {
12         this.subject = subject;
13         subject.addObserver(this);
14         myFile = new File(fileName);
15     }
16     public void hearTelephone(String mess) {
17         try {
18             RandomAccessFile out = new RandomAccessFile(myFile,"rw");
19             out.seek(out.length());
20             byte[] b = mess.getBytes();
21             out.write(b);
22             System.out.println("我是会员一");
23             System.out.println("我向文件"+myFile.getName()+"写入如下内容:");
24             System.out.println(mess);
25         } catch (IOException e) {
26             e.printStackTrace();
27         }
28     }
29     
30 }
复制代码

  UniversityStudent2.java

复制代码
 1 package com.observer;
 2 
 3 import java.io.File;
 4 import java.io.IOException;
 5 import java.io.RandomAccessFile;
 6 
 7 public class UniversityStudent2 implements Observer {
 8     Subject subject;
 9     File myFile;
10     public UniversityStudent2(Subject subject,String fileName) {
11         this.subject = subject;
12         subject.addObserver(this);
13         myFile = new File(fileName);
14     }
15     public void hearTelephone(String mess) {
16         try {
17             boolean boo = mess.contains("促销员")||mess.contains("发单员");
18             if(boo){
19                 RandomAccessFile out = new RandomAccessFile(myFile,"rw");
20                 out.seek(out.length());
21                 byte[] b = mess.getBytes();
22                 out.write(b);
23                 System.out.println("我是会员二");
24                 System.out.println("我向文件"+myFile.getName()+"写入如下内容:");
25                 System.out.println(mess);
26             }
27         } catch (IOException e) {
28             e.printStackTrace();
29         }
30     }
31 }
复制代码

下面写一个测试程序:

复制代码
 1 package com.observer;
 2 
 3 public class Application {
 4     /**
 5      * @param args
 6      */
 7     public static void main(String[] args) {
 8         SeekJobCenter center = new SeekJobCenter();
 9         UniversityStudent zhanglin = new UniversityStudent(center,"zhanglin.txt");
10         UniversityStudent2 wangHao = new UniversityStudent2(center,"wanghao.txt");
11         center.giveNewMess("XX公司需要10个促销员。");
12         center.notifyObservers();
13         center.giveNewMess("XX公司需要8个发单员。");
14         center.notifyObservers();
15         center.giveNewMess("XX公司需要9个临时工。");
16         center.notifyObservers();
17         center.giveNewMess("XX公司需要9个临时工。");
18         center.notifyObservers();
19     }
20 
21 }
复制代码

  运行结果如下:

复制代码
 1 我是会员一
 2 我向文件zhanglin.txt写入如下内容:
 3 XX公司需要10个促销员。
 4 我是会员二
 5 我向文件wanghao.txt写入如下内容:
 6 XX公司需要10个促销员。
 7 我是会员一
 8 我向文件zhanglin.txt写入如下内容:
 9 XX公司需要8个发单员。
10 我是会员二
11 我向文件wanghao.txt写入如下内容:
12 XX公司需要8个发单员。
13 我是会员一
14 我向文件zhanglin.txt写入如下内容:
15 XX公司需要9个临时工。
复制代码

  兼职中心这个例子使用的事观察者模式中的“推”数据方式,也就是说具体主题将变化后的信息全部发送给具体观察者。这种方式往往适用于具体主题认为具体观察者需要这些变化后的全部数据时。

  设计模式中还有另外一种方式也就是“拉”数据方式。如果使用这种方式,具体主题信息一更新,它只会通知所有的观察者:“我的信息已经更新”,具体观察者就可以调用相关方法,获得自己需要的那部分信息。

  下面看另外一个例子:

  问题描述:一家商店每天都发布当天打折商品的名字、原价和折后价,有两位顾客对此信息很感兴趣,但是一位顾客只关心打折商品的名称,而另一位顾客只关心原价和折后价。

  1.主题:

复制代码
1 package com.observer1;
2 
3 public interface Subject {
4     void addObserver(Observer o);
5     void deleteObserver(Observer o);
6     void notifyObservers();
7 }
复制代码

  2.具体主题:

复制代码
 1 package com.observer1;
 2 
 3 import java.util.ArrayList;
 4 
 5 public class ShopSubject implements Subject {
 6     String goodsName;
 7     double oldPrice,newPrice;
 8     ArrayList<Observer> customerList;
 9     public ShopSubject() {
10         customerList = new ArrayList<Observer>();
11     }
12     public void addObserver(Observer o) {
13         if(!(customerList.contains(o))){
14             customerList.add(o);
15         }
16     }
17 
18     public void deleteObserver(Observer o) {
19         if(customerList.contains(o)){
20             customerList.remove(o);
21         }
22     }
23 
24     public void notifyObservers() {
25         for (int i = 0; i < customerList.size(); i++) {
26             Observer o = customerList.get(i);
27             o.update();
28         }
29     }
30     //设置打折商品
31     public void setDiscountGoods(String name,double oldP,double newP){
32         goodsName = name;
33         oldPrice = oldP;
34         newPrice = newP;
35         //设置完通知顾客
36         notifyObservers();
37     }
38     public String getGoodsName() {
39         return goodsName;
40     }
41     public double getOldPrice() {
42         return oldPrice;
43     }
44     public double getNewPrice() {
45         return newPrice;
46     }
47     
48 
49 }
复制代码

  3.观察者:

  这里不是由具体主题直接更新数据过来,所以update()方法不需要传参数过来。

1 package com.observer1;
2 
3 public interface Observer {
4     public void update();
5 }

  4.具体观察者:

CustomerOne对象的顾客只对打折商品的名字感兴趣,对其他信息不感兴趣。

CustomerOne.java

复制代码
 1 package com.observer1;
 2 
 3 public class CustomerOne implements Observer {
 4     Subject subject;
 5     String goodsName,personName;
 6     public CustomerOne(Subject subject,String personName) {
 7         this.personName = personName;
 8         this.subject = subject;
 9         subject.addObserver(this);
10     }
11     public void update() {
12         if(subject instanceof ShopSubject){
13             goodsName = ((ShopSubject)subject).getGoodsName();
14             System.out.println(personName+"只对打折商品的名字感兴趣:");
15             System.out.println("打折商品的名字是:"+goodsName);
16         }
17     }
18 
19 }
复制代码

CustomerTwo的对象的顾客只对商品原价和折后价感兴趣,对商品名称不感兴趣。  

CustomerTwo.java

复制代码
 1 package com.observer1;
 2 
 3 public class CustomerTwo implements Observer {
 4     Subject subject;
 5     String personName;
 6     double oldPrice,newPrice;
 7     public CustomerTwo(Subject subject,String personName) {
 8         this.personName = personName;
 9         this.subject = subject;
10         subject.addObserver(this);
11     }
12     public void update() {
13         if(subject instanceof ShopSubject){
14             oldPrice = ((ShopSubject)subject).getOldPrice();
15             newPrice = ((ShopSubject)subject).getNewPrice();
16             System.out.println(personName+"只对打折商品的原价和折后价感兴趣:");
17             System.out.println("打折商品的原价是:"+oldPrice);
18             System.out.println("打折商品的折后价是:"+newPrice);
19         }
20     }
21 
22 }
复制代码


  下面写一个测试程序:

复制代码
 1 package com.observer1;
 2 
 3 public class Application {
 4     public static void main(String[] args) {
 5         ShopSubject shop = new ShopSubject();
 6         CustomerOne boy  = new CustomerOne(shop,"小明");
 7         CustomerTwo girl = new CustomerTwo(shop,"小红");
 8         shop.setDiscountGoods("Photo数码相机", 2345.6, 2020.0);
 9         shop.setDiscountGoods("三星手机", 2999.0, 2499.0);
10     }
11 }
复制代码

运行结果为:

复制代码
 1 小明只对打折商品的名字感兴趣:
 2 打折商品的名字是:Photo数码相机
 3 小红只对打折商品的原价和折后价感兴趣:
 4 打折商品的原价是:2345.6
 5 打折商品的折后价是:2020.0
 6 小明只对打折商品的名字感兴趣:
 7 打折商品的名字是:三星手机
 8 小红只对打折商品的原价和折后价感兴趣:
 9 打折商品的原价是:2999.0
10 打折商品的折后价是:2499.0
复制代码

 

 

观察者与多主题

  上面两个例子所讲的都是一个具体主题多个观察者的情况。还有一种情况就是一个具体观察者观察多个主题,当观察的任何具体主题的信息发生变化时,该观察者都能得到通知。在使用多主题时,主题应该采用拉数据方式观察者接口可以将更新数据方法的参数类型设置为主题接口类型,比如update(Subject subject),即具体主题数据发生改变时,将自己的引用传递给具体观察者,然后具体观察者让这个具体主题调用相关方法获得信息。

  下面是一个简单的多主题例子

  问题描述:李先生计划去旅游,那么他需要关注旅行社的信息,同时还要关注旅行地区的天气问题。

  根据观察者模式,李先生就是一个具体观察者,而气象站和旅行社就是他观察的两个具体主题。主要代码如下:

  1.主题

复制代码
1 package com.observer2;
2 
3 public interface Subject {
4     void addObserver(Observer o);
5     void deleteObserver(Observer o);
6     void notifyObservers();
7 }
复制代码

  2.观察者

1 package com.observer2;
2 
3 public interface Observer {
4     public void update(Subject subject);
5 }

  3.具体主题:

TravelAgency.java

复制代码
 1 package com.observer2;
 2 
 3 import java.util.ArrayList;
 4 
 5 public class TravelAgency implements Subject{
 6     String tourStartTime;
 7     String tourMess;
 8     ArrayList<Observer> personList;
 9     public TravelAgency() {
10         personList = new ArrayList<Observer>();
11     }
12     public void addObserver(Observer o) {
13         if(o == null){
14             return;
15         }else{
16             if(!(personList.contains(o))){
17                 personList.add(o);
18             }
19         }
20     }
21     public void deleteObserver(Observer o) {
22         if(personList.contains(o)){
23             personList.remove(o);
24         }
25         
26     }
27     public void notifyObservers() {
28         for (int i = 0; i < personList.size(); i++) {
29             Observer o = personList.get(i);
30             o.update(this);
31         }
32     }
33     public void giveMess(String time,String mess){
34         tourStartTime = time;
35         tourMess = mess;
36         notifyObservers();
37     }
38     public String getTourStartTime() {
39         return tourStartTime;
40     }
41     public String getTourMess() {
42         return tourMess;
43     }
44 }
复制代码

WeaherStation.java

复制代码
 1 package com.observer2;
 2 
 3 import java.util.ArrayList;
 4 
 5 public class WeaherStation implements Subject{
 6     String forecastTime,forcastMess;
 7     int maxPemperature,minTemperature;
 8     ArrayList<Observer> personList;
 9     public WeaherStation() {
10         personList = new ArrayList<Observer>();
11     }
12     public void addObserver(Observer o) {
13         if(o == null){
14             return;
15         }else{
16             if(!(personList.contains(o))){
17                 personList.add(o);
18             }
19         }
20     }
21     public void deleteObserver(Observer o) {
22         if(personList.contains(o)){
23             personList.remove(o);
24         }
25         
26     }
27     public void notifyObservers() {
28         for (int i = 0; i < personList.size(); i++) {
29             Observer o = personList.get(i);
30             o.update(this);
31         }
32     }
33     public void doForeCast(String t,String mess,int max,int min){
34         forecastTime = t;
35         forcastMess = mess;
36         minTemperature = min;
37         maxPemperature = max;
38         notifyObservers();
39     }
40     public String getForecastTime() {
41         return forecastTime;
42     }
43     public String getForcastMess() {
44         return forcastMess;
45     }
46     public int getMaxPemperature() {
47         return maxPemperature;
48     }
49     public int getMinTemperature() {
50         return minTemperature;
51     }
52     
53     
54 }
复制代码


具体观察者:

复制代码
 1 package com.observer2;
 2 
 3 public class Person implements Observer {
 4     Subject subjectOne,subjectTwo; //可依赖的主题
 5     String forecastTime,forecastMess;
 6     String tourStartTime,tourMess;
 7     int maxTemperature,minTemperature;
 8     public Person(Subject one,Subject two) {
 9         this.subjectOne = one;
10         this.subjectTwo = two;
11         subjectOne.addObserver(this);
12         subjectTwo.addObserver(this);
13     }
14     public void update(Subject subject) {
15         if(subject instanceof WeaherStation){
16             WeaherStation ws = (WeaherStation)subject;
17             forecastTime = ws.getForecastTime();
18             forecastMess = ws.getForcastMess();
19             maxTemperature = ws.getMaxPemperature();
20             minTemperature = ws.getMinTemperature();
21             System.out.print("预报日期:"+forecastTime+",");
22             System.out.print("天气状况:"+forecastMess+",");
23             System.out.print("最高温度:"+maxTemperature+",");
24             System.out.println("最低温度:"+minTemperature+".");
25         }else if(subject instanceof TravelAgency){
26             TravelAgency ta = (TravelAgency)subject;
27             tourStartTime   = ta.getTourStartTime();
28             tourMess        = ta.getTourMess();
29             System.out.print("旅游开始日期:"+tourStartTime+",");
30             System.out.println("旅游信息:"+tourMess+".");
31         }
32     }
33 
34 }
复制代码

下面写一个测试程序:

复制代码
 1 package com.observer2;
 2 
 3 public class Application {
 4     public static void main(String[] args) {
 5         WeaherStation weaherStation = new WeaherStation();//具体主题
 6         TravelAgency travelAgency   = new TravelAgency(); //具体主题 
 7         Person boy = new Person(weaherStation,travelAgency);

 8         weaherStation.doForeCast("10日", "阴有小雨", 28, 20);
 9         travelAgency.giveMess("10日", "黄山2日游");
10         weaherStation.doForeCast("11日", "晴转多云", 30, 21);
11         travelAgency.giveMess("11日", "丽江1日游");
12     }
13 
14 }
复制代码

运行结果如下:

1 预报日期:10日,天气状况:阴有小雨,最高温度:28,最低温度:20.
2 旅游开始日期:10日,旅游信息:黄山2日游.
3 预报日期:11日,天气状况:晴转多云,最高温度:30,最低温度:21.
4 旅游开始日期:11日,旅游信息:丽江1日游.


 

适合使用观察者模式的情况:

  ①、当一个对象的数据更新时需要通知其他的对象,但这个对象又不希望和被通知的那些对象形成紧耦合。

  ②、当一个对象的数据更新时,这个对象需要让其他对象也各自更新自己的数据,但这个对象不知道具体有多少个对象要更新数据。

 

分享到:
评论

相关推荐

    设计模式 之 观察者模式

    在给定的标题“设计模式 之 观察者模式”中,我们可以理解到这个压缩包文件主要关注的是观察者模式在实际应用中的示例。观察者模式的核心概念包括观察者(Observer)和主题(Subject),其中观察者是接收通知的对象...

    Unity3D设计模式之观察者模式

    观察者模式(Observer Pattern)是一种软件设计模式,属于行为型模式之一。它定义了对象间的一种一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。这种模式可以有效地实现...

    java23种设计模式之观察者模式

    **观察者模式(Observer Pattern)**是软件设计模式中的一种行为模式,它在Java中有着广泛的应用。这个模式的核心思想是“一对多”的依赖关系,即一个主题对象(Subject)可以被多个观察者(Observer)关注,当主题...

    flink-table-api-java-1.12.4.jar中文-英文对照文档.zip

    # 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    基于MPC的微网共享储能日前日内优化调度技术及其实现

    内容概要:本文详细探讨了基于模型预测控制(MPC)的微网共享储能优化调度技术,分为日前优化和日内滚动MPC跟踪两大部分。日前优化部分通过分析居民用电需求,制定储能充放电策略,确保整体能源利用效率最大化。日内滚动MPC跟踪部分则通过预测模型、滚动优化和反馈校正,动态调整储能状态,保持系统稳定。文中提供了多个Python和MATLAB代码片段,展示了具体的技术实现细节,如K-means聚类、CVXPY建模、LSTM+ARIMA混合预测等。 适合人群:从事微网系统设计、储能优化调度的研究人员和技术开发者,以及对模型预测控制感兴趣的工程技术人员。 使用场景及目标:适用于微网系统的储能管理,旨在提高能源利用效率、降低运营成本,并确保系统在各种工况下的稳定性。主要目标是通过合理的储能调度,实现削峰填谷和平抑负荷波动。 其他说明:文章不仅介绍了理论背景,还分享了实际应用中的经验和教训,如处理光伏出力预测误差、优化求解器性能等问题。同时,文中提到的一些关键技术点,如充放电互斥约束、终端约束等,有助于深入理解MPC的应用挑战和解决方案。

    未来互联网:元宇宙、Web3.0与区块链的变革力量

    本书由Bernard Marr撰写,探讨了互联网的第三次演变——未来互联网,即Web 3.0和元宇宙的概念。作者详细分析了元宇宙技术、Web3和区块链如何共同作用,推动互联网向更沉浸式和去中心化的方向发展。书中指出,这一变革不仅将改变我们的日常生活和娱乐方式,还将深刻影响教育、金融、医疗保健以及制造业等多个行业。同时,作者也探讨了政府和公共服务如何利用未来互联网提高效率,以及企业如何在这一变革中重新思考产品、服务和业务运营。书中还强调了未来互联网对技能需求的影响,以及如何在企业中建立适应未来互联网的成功文化,并制定相应的战略。

    flink-connector-jdbc_2.12-1.13.6.jar中文-英文对照文档.zip

    # 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    FPGA中基于VHDL的16阶FIR低通滤波器设计与实现

    内容概要:本文详细介绍了如何使用VHDL语言在FPGA上实现16阶FIR低通滤波器的设计与实现。首先,文中给出了滤波器的基本参数设定,如采样率为50MHz,截止频率为3MHz,并采用汉明窗进行设计。接着,展示了顶层实体声明及其内部逻辑结构,包括移位寄存器作为延迟线以及乘累加操作的具体实现方法。同时提供了完整的VHDL代码片段,涵盖了从顶层实体定义到具体的功能模块,如系数生成、数据移位寄存器和乘累加模块。此外,还讨论了ModelSim仿真的配置与测试激励生成方式,确保仿真结果能够正确反映滤波器性能。最后,针对硬件实现过程中可能出现的问题进行了提示,如时钟约束、资源优化等。 适合人群:具有一定FPGA开发经验的技术人员,尤其是对VHDL编程有一定了解并希望深入研究FIR滤波器实现的人群。 使用场景及目标:适用于需要在FPGA平台上快速搭建并验证FIR低通滤波器的应用场合。主要目标是帮助开发者掌握FIR滤波器的工作原理及其在FPGA上的高效实现方法。 其他说明:文中不仅提供了详细的代码示例,还包括了许多实用的经验分享和技术要点提醒,有助于提高开发效率并减少常见错误的发生。

    车辆紧急防避撞AEB控制系统:基于模糊控制与逆动力学模型的仿真与代码解析

    内容概要:本文详细介绍了车辆紧急防避撞AEB控制系统的构建与实现。首先,文章阐述了驾驶员制动模型,通过模拟人类驾驶者的制动行为,使车辆能够根据实际情况做出适当的制动反应。其次,引入了模糊控制方法用于计算期望减速度,使得车辆能够在面对不确定性环境时作出智能化决策。再次,建立了纵向发动机逆动力学模型,以确定合适的节气门开度,确保车辆的动力输出满足制动需求。此外,还探讨了制动压力与减速度的关系以及风阻和滚动阻力的影响,并展示了具体的代码实现。最后,文章描述了仿真的步骤,强调了验证模型有效性的重要性。 适合人群:从事自动驾驶技术研发的专业人士、对车辆控制感兴趣的工程师和技术爱好者。 使用场景及目标:适用于研究和开发先进的车辆安全辅助系统,旨在提高车辆在紧急情况下的避撞能力,减少交通事故的发生。通过理解和应用文中提供的模型和代码,可以为实际工程项目提供理论支持和技术指导。 其他说明:文章不仅提供了详细的理论解释,还包括了大量的代码示例,便于读者理解和实践。同时,作者还分享了一些实际开发中的经验和技巧,有助于解决可能出现的问题并优化系统性能。

    Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码

    Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码,个人经导师指导并认可通过的高分设计项目,评审分99分,代码完整确保可以运行,小白也可以亲自搞定,主要针对计算机相关专业的正在做大作业的学生和需要项目实战练习的学习者,可作为毕业设计、课程设计、期末大作业,代码资料完整,下载可用。 Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源码Python基于Mapreduce批处理的某招聘网站爬虫及可视化展示项目源

    基于 Python 和 Selenium 的完整网页自动化脚本工具案例,用于模拟用户登录一个示例网站、获取用户信息并退出登录(由于实际网站的结构和元素可能不同,实际使用时需要根据目标网站进行调整)

    脚本功能: 自动打开浏览器。 进入指定的登录页面。 输入预设的用户名和密码。 点击登录按钮。 登录成功后获取用户信息并打印。 点击退出按钮并退出登录。 关闭浏览器。 注意事项: 确保已安装适用于您浏览器的驱动程序,例如 ChromeDriver,并正确设置其路径。 在实际应用中,您需要根据目标网站的结构和元素修改选择器(如 By.NAME、By.ID 等)和相应的值。 此脚本仅为示例,实际使用时需要考虑更复杂的场景,例如异常处理、验证码处理、动态元素加载等。 遵守目标网站的使用条款和法律法规,不要用于非法或未经授权的操作。

    groovy-2.2.2.jar中文文档.zip

    # 压缩文件中包含: 中文文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    【信息安全领域实战项目】

    【信息安全领域实战项目】

    groovy-2.4.15.jar中文文档.zip

    # 压缩文件中包含: 中文文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    基于滑膜控制的五车编队自适应协同巡航仿真与模型研究

    内容概要:本文探讨了基于滑膜控制的五辆车编队实现自适应协同巡航控制(ACC)的研究。通过carsim/Simulink平台进行仿真,采用分层控制结构,上层滑膜控制器根据前车的距离和速度误差计算期望加速度,下层则通过控制节气门开度和制动压力来实现车速控制。文中展示了详细的算法架构、关键代码片段以及丰富的仿真结果图,验证了滑膜控制在车辆编队中的优越性能,特别是在紧急情况下能够迅速反应并保持稳定的跟车距离。 适合人群:对自动驾驶技术和车辆控制系统感兴趣的科研人员、工程师及高校相关专业学生。 使用场景及目标:适用于研究和开发多车编队的自适应巡航控制系统,旨在提高车队行驶的安全性和效率。具体目标包括减少车速跟踪误差、优化节气门和制动控制、提升紧急情况下的响应速度。 其他说明:提供了详细的滑膜控制理论讲解和技术实现细节,附带完整的仿真数据和工程落地指导,有助于读者深入理解和应用该技术。

    flink-table-common-1.13.3.jar中文-英文对照文档.zip

    # 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    三相桥式整流电路双闭环控制系统设计与MATLAB仿真

    内容概要:本文详细介绍了三相桥式整流电路采用双闭环控制(电流内环和电压外环)的方法及其在MATLAB中的仿真实现。首先阐述了为何需要引入电流内环来提高系统的动态响应速度和稳定性,特别是在负载突变情况下。接着描述了硬件配置,包括六个晶闸管的工作方式以及触发脉冲的生成机制。文中给出了具体的双PI控制器参数设置方法,并展示了如何通过调整电流环和电压环的比例和积分系数来优化系统性能。此外,还讨论了常见的调试问题及解决方案,如同步触发信号的相位补偿、PI参数的选择、采样时间的影响等。最后通过仿真实验数据对比,证明了双闭环控制相比单环控制在稳定性和抗干扰方面有着显著优势。 适合人群:从事电力电子研究的技术人员、高校相关专业师生、对电力电子控制系统感兴趣的工程技术人员。 使用场景及目标:适用于需要深入了解三相桥式整流电路双闭环控制原理并进行仿真实践的学习者;旨在帮助读者掌握双闭环控制系统的参数选择、调试技巧及应用实例。 其他说明:文中提供了大量MATLAB代码片段用于辅助理解和实施具体控制策略,同时分享了许多来自实际项目的经验教训,有助于读者更好地将理论应用于实践中。

    基于Matlab的飞蛾扑火优化算法(MFO)详解及其23个测试函数应用

    内容概要:本文详细介绍了飞蛾扑火优化算法(Moth Flame Optimization, MFO)的原理和实现方法。首先解释了MFO的基本概念,即通过模仿飞蛾绕光飞行的行为来构建优化算法。接着展示了MFO的关键公式和Matlab代码实现,特别是飞蛾位置更新公式的具体形式。文中提供了23个经典的测试函数用于评估MFO性能,并给出了具体的调用方式。此外,还讨论了算法运行效果以及一些重要的调参经验和技巧,如种群数量、迭代次数、边界设定等。最后分享了一个实际应用案例,展示了MFO在光伏电池板排布优化中的成功应用。 适合人群:对优化算法感兴趣的科研工作者、学生以及从事相关领域研究的专业人士。 使用场景及目标:适用于需要高效求解复杂优化问题的研究项目,尤其是涉及多峰函数优化的情况。目标是帮助读者掌握MFO的工作原理并能够独立应用于实际问题中。 其他说明:本文不仅提供了详细的理论讲解和技术细节,还包括完整的代码实现和丰富的实验数据,有助于深入理解和实践MFO算法。

    一个通用的数据库管理工具和SQL客户端,具有许多功能,包括元数据编辑器、SQL 编辑器、富数据编辑器、ERD、数据导出/导入/迁移、SQL 执行计划等

    DBeaver 是一个通用的数据库管理工具和 SQL 客户端,具有许多功能,包括元数据编辑器、SQL 编辑器、富数据编辑器、ERD、数据导出/导入/迁移、SQL 执行计划等。支持 MySQL, PostgreSQL, Oracle, DB2, MSSQL, Sybase, Mimer, HSQLDB、Derby、Teradata、Vertica、Netezza、Informix 等。

Global site tag (gtag.js) - Google Analytics