王者榮耀角度下分析面向對象程序設計B中23種設計模式之觀察模式

·觀察者模式在王者榮耀中的應用

·

王者榮耀角度下分析面向對象程序設計B中23種設計模式之觀察模式

一、簡述

王者榮耀是一款5v5的團隊競技遊戲,在一局遊戲當中,必要的系統提示有利於玩家對實時的戰況有更好地把握。比如,當遊戲開局時,系統會提示“敵軍還有5秒到達戰場,請做好準備”;當有英雄被擊殺時或者敵我雙方防禦塔被摧毀時,我方隊友和敵方收到的系統提示是不同的。

於是,此類問題就可以用觀察者模式很好的實現當防禦塔被摧毀後敵我雙方英雄分別收到不同的消息的結果。這裡再簡單描述一下這個具體問題:當敵方高低防禦塔被我方娜可露露摧毀時,我方全部隊友收到系統提示消息“(娜可露露)摧毀敵方防禦塔”,而敵方英雄收到的則是“(娜可露露)摧毀我方防禦塔”。

這裡所述的

“摧毀防禦塔”相當於觀察者模式中的一個具體“主題”

“敵我雙方每位英雄”相當於觀察者模式中的一個具體“觀察者”

二、觀察者模式(Observer Pattern)

觀察者模式理解:

定義對象間的一種一對多的依賴關係,當一個對象的狀態發生變化時,所有依賴於它的對象都得到通知並被自動更新。

觀察者模式是行為模式之一,它的作用是當一個對象的狀態發生變化時,能夠自動通知其他關聯對象,自動刷新對象狀態。

觀察者模式提供給關聯對象一種同步通信的手段,使某個對象與依賴它的其他對象之間保持狀態同步。

觀察者模式結構中的四種角色:

主題(Subject):是一個接口,規定了具體主題需要實現的方法

觀察者(Observer): 是一個接口,規定了具體觀察者用來更新數據的方法

具體主題(ConcreteSubject) :是實現主題接口類的一個實例

具體觀察者(ConcreteObserver):是實現觀察者接口類的一個實例

觀察者模式的UML類圖:

王者榮耀角度下分析面向對象程序設計B中23種設計模式之觀察模式

觀察者模式的優缺點:

優點:

①容易擴展

②滿足“開—閉原則”

③具體主題和具體觀察者是松耦合關係

缺點:

①多級觸發效率較低

②因為是順序執行,一個觀察者卡殼,會影響整體的執行效率

三、王者榮耀角度下實現觀察者模式結構圖及代碼

實現此觀察者模式的UML類圖

王者榮耀角度下分析面向對象程序設計B中23種設計模式之觀察模式

eclipse結構圖

王者榮耀角度下分析面向對象程序設計B中23種設計模式之觀察模式

主函數【應用(Application)】

<code>package angle_observer;
import angle_observer.TeammatesReceive;
import angle_observer.TurretBeenDestroyed;
/*
使用了觀察者模式中所涉及的類,應用程序在使用觀察者模式時,需要創建具體主題和該主題的觀察者

當系統消息提示“敵方防禦塔被摧毀”時,我方和敵方分別得到內容不同的通知
*/
public class Application {
public static void main(String args[]){
\tTurretBeenDestroyed message=new TurretBeenDestroyed(); //具體主題message
\tSystem.out.println(" ");
\tTeammatesReceive teammates=new TeammatesReceive(message,"收到系統消息"); //具體觀察者teammates
\tEnemiesReceive enemies=new EnemiesReceive(message,"收到系統消息"); //具體觀察者enemies
\tmessage.giveNewMess("“敵方防禦塔被摧毀”"); //具體主題給出新信息
\tmessage.notifyObservers(); //具體主題通知信息
}
}/<code>

主題接口

Subject.java

<code>package angle_observer;
import angle_observer.Observer;
/*
角色1:主題:是一個接口,規定了具體主題需要實現的方法
如:添加、刪除觀察者以及通知觀察者更新數據的方法
*/
public interface Subject {
\tpublic void addObserver(Observer o); //規定了具體主題需要實現的添加觀察者更新數據的方法
\tpublic void deleteObserver(Observer o); //規定了具體主題需要實現的刪除觀察者更新數據的方法
\tpublic void notifyObservers(); //規定了具體主題需要實現的通知觀察者更新數據的方法

}/<code>

觀察者接口

Observer.java

<code>package angle_observer;
/*
角色2:觀察者:是一個接口,規定了具體觀察者用來更新數據的方法
*/
public interface Observer {
\tpublic void hearMessage(String mess); //相當於觀察者模式類圖中的update()方法
//要求觀察者都通過實現hearMessage()方法(模擬接收系統消息)來更新數據
}/<code>

具體主題

TurretBeenDestroyed.java

<code>package angle_observer;
/*
角色3:具體主題:是實現主題接口類的一個實例(包含可能經常發生變化的數據)
具體主題需要使用一個集合如ArrayList,存放觀察者的引用,以便數據變化時通知具體觀察者。
*/
import java.util.ArrayList;
public class TurretBeenDestroyed implements Subject{
String mess; //用來表示隊友接收到的消息內容

boolean changed;
ArrayList<observer>informationList; //存放觀察者引用的數組線性表
TurretBeenDestroyed(){
\t informationList=new ArrayList<observer>();
\t mess="";
\t changed=false;
}
public void addObserver(Observer o){
\t if(!(informationList.contains(o)))
\t \t informationList.add(o); //把觀察者的引用添加到數組線性表
}
public void deleteObserver(Observer o){
\t if(informationList.contains(o))
\t \t informationList.remove(o);
}
public void notifyObservers(){
\t if(changed){ //通知所有的觀察者
\t\t for(int i=0;i<informationlist.size>\t\t\t Observer observer=informationList.get(i);
\t\t\t observer.hearMessage(mess); //讓觀察者接收系統消息(執行觀察者接口規定更新數據的方法)
\t\t }
\t\t changed=false;
\t }
}
public void giveNewMess(String str){
\t if(str.equals(mess))
\t\t changed=false;
\t else{
\t\t mess=str;
\t\t changed=true;
\t }
}
}/<informationlist.size>/<observer>/<observer>/<code>

具體觀察者

EnemiesReceive.java

<code>package angle_observer;
/*
角色4.2:具體觀察者:是實現觀察者接口類的一個實例(包含有可以存放具體主題引用的主題接口變量)

讓具體主題引用或刪除自己,使得自己成為或不再是它的觀察者
*/
import java.io.*;
import java.util.regex.*;
public class EnemiesReceive implements Observer{ //實現觀察者接口的第一個類EnemiesReceive
\tSubject subject;
\tFile myFile;
\tEnemiesReceive(Subject subject,String fileName){
\t\tthis.subject=subject;
\t\tsubject.addObserver(this); //使當前實例成為subject所引用的具體主題的觀察者
\t\tmyFile=new File(fileName);
\t}
\tpublic void hearMessage(String heardMess){ //EnemiesReceive類的實例調用hearMessage(String heardMess)方法
\t\ttry{
\t\t\tboolean boo=heardMess.contains("敵方");
\t\t\tif(boo){
\t\t\tRandomAccessFile out=new RandomAccessFile(myFile,"rw"); //若參數引用的字符串中包含有“敵方”,就將信息保存到一個文件中
\t\t\tout.seek(out.length());
\t\t\tbyte[]b=heardMess.getBytes();
\t\t\tout.write(b);
\t\t\tSystem.out.println("-------------------------------------------");
\t\t\tSystem.out.print("【敵方】裴擒虎"+myFile.getName());
\t\t\tSystem.out.println("“我方防禦塔被摧毀”");
\t\t\tSystem.out.print("【敵方】不知火舞"+myFile.getName());
\t\t\tSystem.out.println("“我方防禦塔被摧毀”");
\t\t\tSystem.out.print("【敵方】鍾馗"+myFile.getName());
\t\t\tSystem.out.println("“我方防禦塔被摧毀”");
\t\t\tSystem.out.print("【敵方】李元芳"+myFile.getName());
\t\t\tSystem.out.println("“我方防禦塔被摧毀”");
\t\t\tSystem.out.print("【敵方】典韋"+myFile.getName());
\t\t\tSystem.out.println("“我方防禦塔被摧毀”");
\t\t }
\t\t}

\t\tcatch(IOException exp){
\t\t\tSystem.out.println(exp.toString());
\t\t}
\t}
}/<code>

TeammatesReceive.java

<code>package angle_observer;
/*
角色4:具體觀察者:是實現觀察者接口類的一個實例(包含有可以存放具體主題引用的主題接口變量)
讓具體主題引用或刪除自己,使得自己成為或不再是它的觀察者
*/
import java.io.*;
public class TeammatesReceive implements Observer{ //實現觀察者接口的第一個類TeammatesReceive
\tSubject subject;
\tFile myFile;
\tTeammatesReceive(Subject subject,String fileName){
\t\tthis.subject=subject;
\t\tsubject.addObserver(this); //使當前實例成為subject所引用的具體主題的觀察者
\t\tmyFile= new File(fileName);
\t}
\tpublic void hearMessage(String heardMess){ //TeammatesReceive類的實例調用hearMessage(String heardMess)方法
\t\ttry{
\t\t\tRandomAccessFile out=new RandomAccessFile(myFile,"rw"); //將參數引用的字符串保存到一個文件中
\t\t\tout.seek(out.length());
\t\t\tbyte[]b=heardMess.getBytes();
\t\t\tout.write(b); //更新文件內容
\t\t\tSystem.out.println("【系統消息】敵方防禦塔被摧毀");
\t\t\tSystem.out.println("-------------------------------------------");
\t\t\tSystem.out.print("【我方】娜可露露"+myFile.getName());
\t\t\tSystem.out.println(heardMess);
\t\t\tSystem.out.print("【我方】上官婉兒"+myFile.getName());

\t\t\tSystem.out.println(heardMess);
\t\t\tSystem.out.print("【我方】鬼谷子"+myFile.getName());
\t\t\tSystem.out.println(heardMess);
\t\t\tSystem.out.print("【我方】百里玄策"+myFile.getName());
\t\t\tSystem.out.println(heardMess);
\t\t\tSystem.out.print("【我方】馬可波羅"+myFile.getName());
\t\t\tSystem.out.println(heardMess);
\t\t}
\t\tcatch(IOException exp){
\t\t\tSystem.out.println(exp.toString());
\t\t}
\t}
}/<code>

運行結果截圖

王者榮耀角度下分析面向對象程序設計B中23種設計模式之觀察模式

原文鏈接:https://blog.csdn.net/IT_charge/article/details/104883454

最後給大家分享一波,設計模式文檔和視頻,希望大家能夠喜歡~~
23種設計模式9.35G學習視頻~~

王者榮耀角度下分析面向對象程序設計B中23種設計模式之觀察模式


王者榮耀角度下分析面向對象程序設計B中23種設計模式之觀察模式

王者榮耀角度下分析面向對象程序設計B中23種設計模式之觀察模式


王者榮耀角度下分析面向對象程序設計B中23種設計模式之觀察模式


王者榮耀角度下分析面向對象程序設計B中23種設計模式之觀察模式

23種設計模式文檔~~

王者榮耀角度下分析面向對象程序設計B中23種設計模式之觀察模式


王者榮耀角度下分析面向對象程序設計B中23種設計模式之觀察模式

喜歡的小夥伴可以轉發此文關注小編,小編會持續更新哦~~,還有需要23種設計模式9.35G學習視頻和學習文檔的小夥伴,可以私信小編“模式”來得到獲取方式吧~~~


分享到:


相關文章: