王者荣耀是一款5v5的团队竞技游戏,在一局游戏当中,必要的系统提示有利于玩家对实时的战况有更好地把握。比如,当游戏开局时,系统会提示“敌军还有5秒到达战场,请做好准备”;当有英雄被击杀时或者敌我双方防御塔被摧毁时,我方队友和敌方收到的系统提示是不同的。 于是,此类问题就可以用观察者模式很好的实现当防御塔被摧毁后敌我双方英雄分别收到不同的消息的结果。这里再简单描述一下这个具体问题:当敌方高低防御塔被我方娜可露露摧毁时,我方全部队友收到系统提示消息“(娜可露露)摧毁敌方防御塔”,而敌方英雄收到的则是“(娜可露露)摧毁我方防御塔”。
这里所述的 “摧毁防御塔”相当于观察者模式中的一个具体“主题” “敌我双方每位英雄”相当于观察者模式中的一个具体“观察者”
观察者模式理解: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖于它的对象都得到通知并被自动更新。 观察者模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态。 观察者模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对象之间保持状态同步。
观察者模式结构中的四种角色: 主题(Subject):是一个接口,规定了具体主题需要实现的方法 观察者(Observer): 是一个接口,规定了具体观察者用来更新数据的方法 具体主题(ConcreteSubject) :是实现主题接口类的一个实例 具体观察者(ConcreteObserver):是实现观察者接口类的一个实例
观察者模式的UML类图:
观察者模式的优缺点: 优点: ①容易扩展 ②满足“开—闭原则” ③具体主题和具体观察者是松耦合关系 缺点: ①多级触发效率较低 ②因为是顺序执行,一个观察者卡壳,会影响整体的执行效率
实现此观察者模式的UML类图
eclipse结构图
主函数【应用(Application)】
package angle_observer;
import angle_observer.TeammatesReceive;
import angle_observer.TurretBeenDestroyed;
/*
使用了观察者模式中所涉及的类,应用程序在使用观察者模式时,需要创建具体主题和该主题的观察者
当系统消息提示“敌方防御塔被摧毁”时,我方和敌方分别得到内容不同的通知
*/
public class Application {
public static void main(String args[]){
TurretBeenDestroyed message=new TurretBeenDestroyed(); //具体主题message
System.out.println(" ");
TeammatesReceive teammates=new TeammatesReceive(message,"收到系统消息"); //具体观察者teammates
EnemiesReceive enemies=new EnemiesReceive(message,"收到系统消息"); //具体观察者enemies
message.giveNewMess("“敌方防御塔被摧毁”"); //具体主题给出新信息
message.notifyObservers(); //具体主题通知信息
}
}
123456789101112131415161718192021
主题接口 Subject.java
package angle_observer;
import angle_observer.Observer;
/*
角色1:主题:是一个接口,规定了具体主题需要实现的方法
如:添加、删除观察者以及通知观察者更新数据的方法
*/
public interface Subject {
public void addObserver(Observer o); //规定了具体主题需要实现的添加观察者更新数据的方法
public void deleteObserver(Observer o); //规定了具体主题需要实现的删除观察者更新数据的方法
public void notifyObservers(); //规定了具体主题需要实现的通知观察者更新数据的方法
}
12345678910111213141516
观察者接口 Observer.java
package angle_observer;
/*
角色2:观察者:是一个接口,规定了具体观察者用来更新数据的方法
*/
public interface Observer {
public void hearMessage(String mess); //相当于观察者模式类图中的update()方法
//要求观察者都通过实现hearMessage()方法(模拟接收系统消息)来更新数据
}
1234567891011
具体主题 TurretBeenDestroyed.java
package angle_observer;
/*
角色3:具体主题:是实现主题接口类的一个实例(包含可能经常发生变化的数据)
具体主题需要使用一个集合如ArrayList,存放观察者的引用,以便数据变化时通知具体观察者。
*/
import java.util.ArrayList;
public class TurretBeenDestroyed implements Subject{
String mess; //用来表示队友接收到的消息内容
boolean changed;
ArrayList<Observer>informationList; //存放观察者引用的数组线性表
TurretBeenDestroyed(){
informationList=new ArrayList<Observer>();
mess="";
changed=false;
}
public void addObserver(Observer o){
if(!(informationList.contains(o)))
informationList.add(o); //把观察者的引用添加到数组线性表
}
public void deleteObserver(Observer o){
if(informationList.contains(o))
informationList.remove(o);
}
public void notifyObservers(){
if(changed){ //通知所有的观察者
for(int i=0;i<informationList.size();i++){ //遍历具体主题中用来存放观察者引用的集合
Observer observer=informationList.get(i);
observer.hearMessage(mess); //让观察者接收系统消息(执行观察者接口规定更新数据的方法)
}
changed=false;
}
}
public void giveNewMess(String str){
if(str.equals(mess))
changed=false;
else{
mess=str;
changed=true;
}
}
}
123456789101112131415161718192021222324252627282930313233343536373839404142434445
具体观察者 EnemiesReceive.java
package angle_observer;
/*
角色4.2:具体观察者:是实现观察者接口类的一个实例(包含有可以存放具体主题引用的主题接口变量)
让具体主题引用或删除自己,使得自己成为或不再是它的观察者
*/
import java.io.*;
import java.util.regex.*;
public class EnemiesReceive implements Observer{ //实现观察者接口的第一个类EnemiesReceive
Subject subject;
File myFile;
EnemiesReceive(Subject subject,String fileName){
this.subject=subject;
subject.addObserver(this); //使当前实例成为subject所引用的具体主题的观察者
myFile=new File(fileName);
}
public void hearMessage(String heardMess){ //EnemiesReceive类的实例调用hearMessage(String heardMess)方法
try{
boolean boo=heardMess.contains("敌方");
if(boo){
RandomAccessFile out=new RandomAccessFile(myFile,"rw"); //若参数引用的字符串中包含有“敌方”,就将信息保存到一个文件中
out.seek(out.length());
byte[]b=heardMess.getBytes();
out.write(b);
System.out.println("-------------------------------------------");
System.out.print("【敌方】裴擒虎"+myFile.getName());
System.out.println("“我方防御塔被摧毁”");
System.out.print("【敌方】不知火舞"+myFile.getName());
System.out.println("“我方防御塔被摧毁”");
System.out.print("【敌方】钟馗"+myFile.getName());
System.out.println("“我方防御塔被摧毁”");
System.out.print("【敌方】李元芳"+myFile.getName());
System.out.println("“我方防御塔被摧毁”");
System.out.print("【敌方】典韦"+myFile.getName());
System.out.println("“我方防御塔被摧毁”");
}
}
catch(IOException exp){
System.out.println(exp.toString());
}
}
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546
TeammatesReceive.java
package angle_observer;
/*
角色4:具体观察者:是实现观察者接口类的一个实例(包含有可以存放具体主题引用的主题接口变量)
让具体主题引用或删除自己,使得自己成为或不再是它的观察者
*/
import java.io.*;
public class TeammatesReceive implements Observer{ //实现观察者接口的第一个类TeammatesReceive
Subject subject;
File myFile;
TeammatesReceive(Subject subject,String fileName){
this.subject=subject;
subject.addObserver(this); //使当前实例成为subject所引用的具体主题的观察者
myFile= new File(fileName);
}
public void hearMessage(String heardMess){ //TeammatesReceive类的实例调用hearMessage(String heardMess)方法
try{
RandomAccessFile out=new RandomAccessFile(myFile,"rw"); //将参数引用的字符串保存到一个文件中
out.seek(out.length());
byte[]b=heardMess.getBytes();
out.write(b); //更新文件内容
System.out.println("【系统消息】敌方防御塔被摧毁");
System.out.println("-------------------------------------------");
System.out.print("【我方】娜可露露"+myFile.getName());
System.out.println(heardMess);
System.out.print("【我方】上官婉儿"+myFile.getName());
System.out.println(heardMess);
System.out.print("【我方】鬼谷子"+myFile.getName());
System.out.println(heardMess);
System.out.print("【我方】百里玄策"+myFile.getName());
System.out.println(heardMess);
System.out.print("【我方】马可波罗"+myFile.getName());
System.out.println(heardMess);
}
catch(IOException exp){
System.out.println(exp.toString());
}
}
}
123456789101112131415161718192021222324252627282930313233343536373839404142
运行结果截图
更多设计模式在王者荣耀中的应用请点击我的→设计模式在王者荣耀中的应用专栏
感谢阅读
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。