观察者模式和模拟wow插件的例子

观察者模式的定义:[color=red]在对象之间定义一对多的依赖,当一个对象改变状态时,依赖它的对象都会收到通知,并自动更新。[/color]

说白了就像是:有一群人订了同一家报纸,当这个报纸出新版的时候,会派报童给每个订阅了自己的人一份最新的报纸,然后不同的订阅人收到报纸后,自己处理,可以看看新闻,可以叠成飞机,可以用来防止上厕所时没带纸。。。订阅者收到报纸后怎么样,已经不管这家报纸发行商的事了。
订阅人可以取消订阅,没订阅的人也可以加入订阅的行列。

[color=blue]WOW扫盲,写给没玩过WOW的java人们:
WOW:魔兽世界
BOSS:这个大家都知道,每个游戏都有BOSS,就是个怪物的首领
TANK:也就是大家常说的肉盾,把BOSS的仇恨吸引到自己身上来,好让其他人打BOSS
DPS:打手,BOSS打TANK,DPS打BOSS
Healther:治疗,俗称奶妈,BOSS打TANK,奶妈给TANK加血。[/color]

现在用这种模式来模拟一个WOW的插件。
假设,WOW中有一个BOSS,他的技能分两个阶段。
第一阶段的时候,只用TANK拉好了,DPS们只管打就是了,奶妈治疗TANK。
第二阶段的时候,BOSS会在地面上方火焰,TANK依然是拉好BOSS,但需要躲地上的火焰,DPS们依然是打BOSS,也需要躲火焰,奶妈这个时候不但要为TANK加血,也要为DPS加血(有的DPS可能被火烧到)。

我们要做的东西,就是为队长写一个插件,让这个插件可以自动给队里的每个角色分配任务。
我们希望BOSS在第一阶段的时候,奶妈可以自动收到一个提示“请全力治疗Tank。”,而DPS收到的提示却是“请全力输出BOSS。”
插件为每个玩家配置一个发信的工具,为了方便就叫话筒吧,话筒去对玩家发送消息。

我们可以把BOSS看做是一个被观察的主题,而小队中所有玩家对应的话筒都是观察者。一但BOSS进入了第一阶段,也就是BOSS状态变了,那么所有观察者(也就是话筒)都会受到相应的通知,并对自己对应的玩家发送消息。


现在看代码:

package com.subject;

import com.observer.I_Observer;
//被观察的主题的接口
public interface I_Subject {
//注册一个观察者
public void registerObserver(I_Observer o);
//删除一个观察者
public void removeObserver(I_Observer o);
//通知所有观察者
public void notifyObserver();
}




package com.subject;

import java.util.ArrayList;

import com.observer.I_Observer;
//假设这是插件用来检测BOSS状态的监听器。这里并没有实现监听功能。
public class BossListener implements I_Subject {
ArrayList<I_Observer> listOfObserver;
int status;

public BossListener() {
listOfObserver = new ArrayList<I_Observer>();
status = 1;
}

public int getStatus() {
return status;
}

public void setStatus(int status) {

this.status = status;
this.notifyObserver();
}
//通知所有观察者,并告诉观察者自己当前的状态
@Override
public void notifyObserver() {
for (I_Observer o : listOfObserver) {
o.update(this.status);
}
}

@Override
public void registerObserver(I_Observer o) {
this.listOfObserver.add(o);
}

@Override
public void removeObserver(I_Observer o) {
int index = this.listOfObserver.indexOf(o);
if (index >= 0) {
this.listOfObserver.remove(index);
}
}

}




package com.observer;
//观察者的接口
public interface I_Observer {
//状态改变时执行的动作
public void update(int status);
}




package com.observer;

public abstract class Player implements I_Observer {
//玩家的名字
String name;
//在第一阶段时,对玩家的提示。
String suggestion1;
//在第二阶段时,对玩家的提示。
String suggestion2;
//在第三阶段时,对玩家的提示。
String suggestion3;

public String getSuggestion1() {
return suggestion1;
}

public void setSuggestion1(String suggestion1) {
this.suggestion1 = suggestion1;
}

public String getSuggestion2() {
return suggestion2;
}

public void setSuggestion2(String suggestion2) {
this.suggestion2 = suggestion2;
}

public String getSuggestion3() {
return suggestion3;
}

public void setSuggestion3(String suggestion3) {
this.suggestion3 = suggestion3;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
//根据不同阶段,发送不同的通知消息。
public void update(int status) {
if (status == 1) {
System.out.println("插件提示:Boss进入了第一阶段," + this.getName()
+ suggestion1);
} else if (status == 2) {
System.out.println("插件提示:Boss进入了第二阶段," + this.getName()
+ suggestion2);
} else if (status == 3) {
System.out.println("插件提示:Boss已经死亡,恭喜" + suggestion3);
}
}


}




package com.observer;

public class Tank extends Player {

public Tank(String name) {
this.name = name;
this.name=name;
this.suggestion1 = "请保持BOSS的仇恨";
this.suggestion2 = "请保持BOSS的仇恨并躲好地上的火焰。";
this.suggestion3 = ",BOSS已经死亡。";
}
//通知的逻辑已经在父类写过了,这里只用更改自己通知时的消息就行了
@Override
public void update(int status) {
super.update(status);
}

}




package com.observer;

public class DPS extends Player {
public DPS(String name)
{
this.name=name;
this.suggestion1 = "请全力输出BOSS。";
this.suggestion2 = "请全力输出BOSS并躲好地上的火焰。";
this.suggestion3 = ",BOSS已经死亡。";
}

@Override
public void update(int status) {
super.update(status);
}

}




package com.observer;

public class Healther extends Player {
public Healther(String name) {
this.name = name;
this.suggestion1 = "请全力治疗Tank。";
this.suggestion2 = "请对全团治疗,保持团血在百分之50以上。";
this.suggestion3 = ",BOSS已经死亡。";
}

@Override
public void update(int status) {
super.update(status);
}

}



测试类:

package com.test;

import com.observer.DPS;
import com.observer.Healther;
import com.observer.Tank;
import com.subject.BossListener;

public class Test {
public static void main(String[] args) {
BossListener listener =new BossListener();
listener.registerObserver(new Tank("MT"));
listener.registerObserver(new Tank("2T"));
listener.registerObserver(new DPS("DPS1"));
listener.registerObserver(new Healther("Healther1"));
listener.setStatus(1);
listener.setStatus(2);
listener.setStatus(3);

}
}




插件提示:Boss进入了第一阶段,MT请保持BOSS的仇恨
插件提示:Boss进入了第一阶段,2T请保持BOSS的仇恨
插件提示:Boss进入了第一阶段,DPS1请全力输出BOSS。
插件提示:Boss进入了第一阶段,Healther1请全力治疗Tank。
插件提示:Boss进入了第二阶段,MT请保持BOSS的仇恨并躲好地上的火焰。
插件提示:Boss进入了第二阶段,2T请保持BOSS的仇恨并躲好地上的火焰。
插件提示:Boss进入了第二阶段,DPS1请全力输出BOSS并躲好地上的火焰。
插件提示:Boss进入了第二阶段,Healther1请对全团治疗,保持团血在百分之50以上。
插件提示:Boss已经死亡,恭喜,BOSS已经死亡。
插件提示:Boss已经死亡,恭喜,BOSS已经死亡。
插件提示:Boss已经死亡,恭喜,BOSS已经死亡。
插件提示:Boss已经死亡,恭喜,BOSS已经死亡。



看完这些代码和执行结果,再回头看一下观察者模式的定义:
[color=red]在对象之间定义一对多的依赖,当一个对象改变状态时,依赖它的对象都会收到通知,并自动更新。 [/color]

多个观察者依赖同一个BOSS监听器,BOSS监听器监听到BOSS状态改变,则通知所有话筒,这些观察者做出了各自的反应。


当然,写这个主要是为了巩固观察者模式,WOW插件只是个例子,真正的WOW插件是很复杂的。。。

[color=blue]最后,身为一个WOWer向所有WOW插件开发者敬礼。[/color]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值