物件間的聯動——觀察者模式(三)

Liuwei-Sunny發表於2012-07-05

23.3 完整解決方案

      為了實現物件之間的聯動,Sunny軟體公司開發人員決定使用觀察者模式來進行多人聯機對戰遊戲的設計,其基本結構如圖22-4所示:

22-4  多人聯機對戰遊戲結構圖

      在圖22-4中,AllyControlCenter充當目標類,ConcreteAllyControlCenter充當具體目標類,Observer充當抽象觀察者,Player充當具體觀察者。完整程式碼如下所示:

import java.util.*;

//抽象觀察類
interface Observer {
	public String getName();
	public void setName(String name);
	public void help(); //宣告支援盟友方法
	public void beAttacked(AllyControlCenter acc); //宣告遭受攻擊方法
}

//戰隊成員類:具體觀察者類
class Player implements Observer {
	private String name;

	public Player(String name) {
		this.name = name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public String getName() {
		return this.name;
	}
	
    //支援盟友方法的實現
	public void help() {
		System.out.println("堅持住," + this.name + "來救你!");
	}
	
    //遭受攻擊方法的實現,當遭受攻擊時將呼叫戰隊控制中心類的通知方法notifyObserver()來通知盟友
	public void beAttacked(AllyControlCenter acc) {
        System.out.println(this.name + "被攻擊!");
        acc.notifyObserver(name);		
	}
}

//戰隊控制中心類:目標類
abstract class AllyControlCenter {
	protected String allyName; //戰隊名稱
	protected ArrayList<Observer> players = new ArrayList<Observer>(); //定義一個集合用於儲存戰隊成員
	
	public void setAllyName(String allyName) {
		this.allyName = allyName;
	}
	
	public String getAllyName() {
		return this.allyName;
	}
	
    //註冊方法
	public void join(Observer obs) {
		System.out.println(obs.getName() + "加入" + this.allyName + "戰隊!");
		players.add(obs);
	}
	
    //登出方法
	public void quit(Observer obs) {
		System.out.println(obs.getName() + "退出" + this.allyName + "戰隊!");
		players.remove(obs);
	}
	
    //宣告抽象通知方法
	public abstract void notifyObserver(String name);
}

//具體戰隊控制中心類:具體目標類
class ConcreteAllyControlCenter extends AllyControlCenter {
	public ConcreteAllyControlCenter(String allyName) {
		System.out.println(allyName + "戰隊組建成功!");
		System.out.println("----------------------------");
		this.allyName = allyName;
	}
	
    //實現通知方法
	public void notifyObserver(String name) {
		System.out.println(this.allyName + "戰隊緊急通知,盟友" + name + "遭受敵人攻擊!");
        //遍歷觀察者集合,呼叫每一個盟友(自己除外)的支援方法
        for(Object obs : players) {
            if (!((Observer)obs).getName().equalsIgnoreCase(name)) {
                ((Observer)obs).help();
            }
        }		
	}
}

      編寫如下客戶端測試程式碼:

class Client {
	public static void main(String args[]) {
		//定義觀察目標物件
AllyControlCenter acc;
		acc = new ConcreteAllyControlCenter("金庸群俠");
		
        //定義四個觀察者物件
		Observer player1,player2,player3,player4;
		
		player1 = new Player("楊過");
		acc.join(player1);
		
		player2 = new Player("令狐沖");
		acc.join(player2);
		
		player3 = new Player("張無忌");
		acc.join(player3);
		
		player4 = new Player("段譽");
		acc.join(player4);
		
		//某成員遭受攻擊
		Player1.beAttacked(acc);
	}
}

      編譯並執行程式,輸出結果如下:

金庸群俠戰隊組建成功!

----------------------------

楊過加入金庸群俠戰隊!

令狐沖加入金庸群俠戰隊!

張無忌加入金庸群俠戰隊!

段譽加入金庸群俠戰隊!

楊過被攻擊!

金庸群俠戰隊緊急通知,盟友楊過遭受敵人攻擊!

堅持住,令狐沖來救你!

堅持住,張無忌來救你!

堅持住,段譽來救你!

      在本例項中,實現了兩次物件之間的聯動,當一個遊戲玩家Player物件的beAttacked()方法被呼叫時,將呼叫AllyControlCenternotifyObserver()方法來進行處理,而在notifyObserver()方法中又將呼叫其他Player物件的help()方法。PlayerbeAttacked()方法、AllyControlCenternotifyObserver()方法以及Playerhelp()方法構成了一個聯動觸發鏈,執行順序如下所示:

Player.beAttacked() --> AllyControlCenter.notifyObserver() -->Player.help()

【作者:劉偉   http://blog.csdn.net/lovelion

相關文章