天天看點

對象間的關聯——觀察者模式(三)

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()方法被調用時,将調用AllyControlCenter的notifyObserver()方法來進行處理,而在notifyObserver()方法中又将調用其他Player對象的help()方法。Player的beAttacked()方法、AllyControlCenter的notifyObserver()方法以及Player的help()方法構成了一個關聯觸發鍊,執行順序如下所示:

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

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