《星际争霸》与设计模式(3)——观察者模式
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《星际争霸》与设计模式(3)——观察者模式
昨天我们讲到⼈族毫⽆准备的情况下被神族空降⾦甲⾍偷袭了⼀把,损失惨重,于是⼈族⾼层召开会议,总结教训,商讨应对⽅法,经过商讨,决定在各处设置警报点,并且给该警报点警卫⼀份名单,要求⼀旦警报点发出警报时,警卫⽴即通知名单上的所有部队!⽽且随着不同局势的变化,可以对名单上的成员进⾏修改!这⼀系列部署程序上称为抽象主题。
符合这⼀主题的警报点有很多,⽐如位置a点的防空塔,这个防空塔程序上称为具体主题,此时要求所有部队,⼀旦接到警报通知,马上作出防御或还击,没有接到通知的就各⼲各的事,在程序⾥就是定义了⼀个接⼝或抽象类,制定了⼀条对警报作出反应的规定,我们称为抽象观察者,a点防空塔的警卫将符合这条规定的4部分⼈马:scv,坦克1队,坦克2对,隐形战机加⼊了通知名单(他们都来⾃不同的类,但都属于抽象观察者的之类,符合接⼝,能对警报作出反应),只要发⽣警报就通知者4部分⼈马!程序⾥我们称这4部分⼈马为具体观察者。
这样就可以以不变应万变!
下⾯看看类图
using System;
using System.Collections;
namespace starcraft.ObserverPattern
{
//------------抽象主题⾓⾊------------
abstract class Alarm //警报,警报的抽象定义
{
protected string alarmsignal=""; //代表警报器的状态,通常状况下⽆信号!
protected string place; //发⽣警报的位置;
private ArrayList Armys = new ArrayList(); //发⽣警报时要通知作出反应的部队列表
public Alarm(string where) //事例化⼀个警报,代表在某地⽅设置警报监视器
{
this.place = where;
}
public void Add(ITerranArmy army) //将某⼀个部队加⼊通知列表,可以是坦克,战机……
{
Armys.Add(army);
}
public void Remove(ITerranArmy army) //将某⼀个部队从通知列表中移出
{
Armys.Remove(army);
}
public void Notify() //将警报发给所有要通知的部队,他们将作出相应⾏动!
{
foreach (ITerranArmy Army in Armys)
Army.Forestall(this);
}
public string Alarmsignal
{
get { return alarmsignal; }
set
{
alarmsignal = value;
Notify(); //当警报器状态发⽣警报时,发出警报通知
}
}
public string Place
{
get { return place; }
set { place = value; }
}
}
//------------具体主题⾓⾊------------
class MissileTurret : Alarm //⼀个具体的警报,防空塔警报
{
public MissileTurret(string where): base(where) { }
}
//------------抽象观察者⾓⾊------------
interface ITerranArmy //⼀个抽象的⼈族部队
{
void Forestall(Alarm larum); //当接到某⼀种警报是作出相应⾏动来应对警报!
}
//------------3类具体观察者⾓⾊------------
class TankArmy : ITerranArmy //坦克部队,⼀个具体的⼈族部队
{
private String name ; //部队名
private String state = "在路⼝巡逻"; //正常时,坦克部队的状态;
public void Forestall(Alarm larum) //当接到通知后改变状态,前往警报地点
{
this.state = "到达" + larum.Place + ",展开,准备开⽕";
Console.WriteLine( + ":" + this.State); //将状态输出
}
public string Name
{
get { return name; }
set { name = value; }
}
public string State
{
get { return state; }
set { state = value; }
}
public TankArmy(string name)
{
= name;
}
}
class WraithArmy : ITerranArmy //幽灵战机部队,⼀个具体的⼈族部队
{
private String name; //部队名
private String state = "在前线待命"; //正常时,战机部队的状态;
public void Forestall(Alarm larum) //当接到通知后改变状态,前往警报地点
{
this.state = "飞往" + larum.Place + ",隐形,准备开⽕";
Console.WriteLine( + ":" + this.State); //将状态输出
}
public string Name
{
get { return name; }
set { name = value; }
}
public string State
{
get { return state; }
set { state = value; }
}
public WraithArmy(string name)
{
= name;
}
}
class SCV : ITerranArmy //采矿农民,⼀个具体的⼈族部队
{
private String name; //部队名
private String state = "采矿"; //正常时,战机部队的状态;
public void Forestall(Alarm larum) //当接到通知后改变状态,远离警报地点
{
this.state = "远离" + larum.Place + ",到达安全地区";
Console.WriteLine( + ":" + this.State); //将状态输出
}
public string Name
{
get { return name; }
set { name = value; }
}
public string State
{
get { return state; }
set { state = value; }
}
public SCV(string name)
{
= name;
}
}
//----------------------------------------
class game //具体游戏情景
{
static void Main(string[] args)
{
Alarm alarm = new MissileTurret("A点"); //在A点设置⼀个警报器;
//分别实例化4个⼈族部队作为我们的观察对象,并记录各个部队的状态,⽅便⼤家进⾏前后对⽐ SCV scv = new SCV("SCV");
TankArmy tank1 = new TankArmy("坦克部队1");
TankArmy tank2 = new TankArmy("坦克部队2");
WraithArmy wraith = new WraithArmy("隐形战机");
Console.WriteLine("-----正常状态下各个部队的状态");
Console.WriteLine( + ":" + scv.State);
Console.WriteLine( + ":" + tank1.State);
Console.WriteLine( + ":" + tank2.State);
Console.WriteLine( + ":" + wraith.State);
//将这4个对象加⼊到警报通知列表;
alarm.Add(scv);
alarm.Add(tank1);
alarm.Add(tank2);
alarm.Add(wraith);
Console.WriteLine("-----在A点设置的警报器发⽣了警报信号");
alarm.Alarmsignal = "发现神族运输机"; //防空塔发现了神族运输机,状态改变;
//⼤家仔细看看这⼀步,随着防空塔状态的改变,以上⼏个部队的状态都改变了!
Console.WriteLine("-----⼈族部队未损失⼀兵⼀卒,击落来侵犯的所有敌军!");
}
}
}
运⾏结果:
经过⼀来⼀回两次交锋,双⽅互有胜负,战成平⼿!局⾯进⼊僵持阶段!那么随着游戏的发展⼈族是如何把握战局,占据主动,迎来最后的胜利,我们慢慢说来!。