对象间的联动——观察者模式(三)

23.3 完整解决方案

为了实现对象之间的联动,Sunny软件公司开发人员决定使用观察者模式来进行多人联机对战游戏的设计,其基本结构如图22-4所示:

对象间的联动——观察者模式(三) - 图1

图22-4 多人联机对战游戏结构图 在图22-4中,AllyControlCenter充当目标类,ConcreteAllyControlCenter充当具体目标类,Observer充当抽象观察者,Player充当具体观察者。完整代码如下所示:

  1. import java.util.*;
  2. //抽象观察类
  3. interface Observer {
  4. public String getName();
  5. public void setName(String name);
  6. public void help(); //声明支援盟友方法
  7. public void beAttacked(AllyControlCenter acc); //声明遭受攻击方法
  8. }
  9. //战队成员类:具体观察者类
  10. class Player implements Observer {
  11. private String name;
  12. public Player(String name) {
  13. this.name = name;
  14. }
  15. public void setName(String name) {
  16. this.name = name;
  17. }
  18. public String getName() {
  19. return this.name;
  20. }
  21. //支援盟友方法的实现
  22. public void help() {
  23. System.out.println("坚持住," + this.name + "来救你!");
  24. }
  25. //遭受攻击方法的实现,当遭受攻击时将调用战队控制中心类的通知方法notifyObserver()来通知盟友
  26. public void beAttacked(AllyControlCenter acc) {
  27. System.out.println(this.name + "被攻击!");
  28. acc.notifyObserver(name);
  29. }
  30. }
  31. //战队控制中心类:目标类
  32. abstract class AllyControlCenter {
  33. protected String allyName; //战队名称
  34. protected ArrayList<Observer> players = new ArrayList<Observer>(); //定义一个集合用于存储战队成员
  35. public void setAllyName(String allyName) {
  36. this.allyName = allyName;
  37. }
  38. public String getAllyName() {
  39. return this.allyName;
  40. }
  41. //注册方法
  42. public void join(Observer obs) {
  43. System.out.println(obs.getName() + "加入" + this.allyName + "战队!");
  44. players.add(obs);
  45. }
  46. //注销方法
  47. public void quit(Observer obs) {
  48. System.out.println(obs.getName() + "退出" + this.allyName + "战队!");
  49. players.remove(obs);
  50. }
  51. //声明抽象通知方法
  52. public abstract void notifyObserver(String name);
  53. }
  54. //具体战队控制中心类:具体目标类
  55. class ConcreteAllyControlCenter extends AllyControlCenter {
  56. public ConcreteAllyControlCenter(String allyName) {
  57. System.out.println(allyName + "战队组建成功!");
  58. System.out.println("----------------------------");
  59. this.allyName = allyName;
  60. }
  61. //实现通知方法
  62. public void notifyObserver(String name) {
  63. System.out.println(this.allyName + "战队紧急通知,盟友" + name + "遭受敌人攻击!");
  64. //遍历观察者集合,调用每一个盟友(自己除外)的支援方法
  65. for(Object obs : players) {
  66. if (!((Observer)obs).getName().equalsIgnoreCase(name)) {
  67. ((Observer)obs).help();
  68. }
  69. }
  70. }
  71. }

编写如下客户端测试代码:

  1. class Client {
  2. public static void main(String args[]) {
  3. //定义观察目标对象
  4. AllyControlCenter acc;
  5. acc = new ConcreteAllyControlCenter("金庸群侠");
  6. //定义四个观察者对象
  7. Observer player1,player2,player3,player4;
  8. player1 = new Player("杨过");
  9. acc.join(player1);
  10. player2 = new Player("令狐冲");
  11. acc.join(player2);
  12. player3 = new Player("张无忌");
  13. acc.join(player3);
  14. player4 = new Player("段誉");
  15. acc.join(player4);
  16. //某成员遭受攻击
  17. Player1.beAttacked(acc);
  18. }
  19. }

编译并运行程序,输出结果如下:

  1. 金庸群侠战队组建成功!
  2. ----------------------------
  3. 杨过加入金庸群侠战队!
  4. 令狐冲加入金庸群侠战队!
  5. 张无忌加入金庸群侠战队!
  6. 段誉加入金庸群侠战队!
  7. 杨过被攻击!
  8. 金庸群侠战队紧急通知,盟友杨过遭受敌人攻击!
  9. 坚持住,令狐冲来救你!
  10. 坚持住,张无忌来救你!
  11. 坚持住,段誉来救你!

在本实例中,实现了两次对象之间的联动,当一个游戏玩家Player对象的beAttacked()方法被调用时,将调用AllyControlCenter的notifyObserver()方法来进行处理,而在notifyObserver()方法中又将调用其他Player对象的help()方法。Player的beAttacked()方法、AllyControlCenter的notifyObserver()方法以及Player的help()方法构成了一个联动触发链,执行顺序如下所示:

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