一.观察者模式
观察者模式是使用频率最高的设计模式之一,它用于建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应作出反应。在观察者模式中,发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应多个观察者,而且这些观察者之间可以没有任何相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展。
观察者模式定义如下: 观察者模式(Observer Pattern):定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。
二.多人对战游戏
Sunny软件公司欲开发一款多人联机对战游戏(类似魔兽世界、星际争霸等游戏),在该游戏中,多个玩家可以加入同一战队组成联盟,当战队中某一成员受到敌人攻击时将给所有其他盟友发送通知,盟友收到通知后将作出响应。
Sunny软件公司开发人员需要提供一个设计方案来实现战队成员之间的联动。Sunny软件公司开发人员通过对系统功能需求进行分析,发现在该系统中战队成员之间的联动过程可以简单描述如下:联盟成员受到攻击-->发送通知给盟友-->盟友作出响应。
如果按照上述思路来设计系统,由于联盟成员在受到攻击时需要通知他的每一个盟友,因此每个联盟成员都需要持有其他所有盟友的信息,这将导致系统开销较大,因此Sunny公司开发人员决定引入一个新的角色——“战队控制中心”——来负责维护和管理每个战队所有成员的信息。当一个联盟成员受到攻击时,将向相应的战队控制中心发送求助信息,战队控制中心再逐一通知每个盟友,盟友再作出响应
结构图如下:
三.代码实现
目标类:AllyControlCenter
https://github.com/Aro710/Game_mul/blob/master/observer/demo/AllyControlCenter.java
public abstract class AllyControlCenter { /** * 战队名称 */ protected String allyName; /** * 定义一个集合用于存储战队成员 */ protected List<Observer> players = new ArrayList<Observer>(); public String getAllyName() { return allyName; } public void setAllyName(String allyName) { this.allyName = allyName; } /** * 注册方法 * @param player */ public void join(Observer player){ System.out.println(MessageFormat.format("{0}加入{1}战队", player.getName(), this.allyName)); players.add(player); } /** * 注销方法 * @param player */ public void quit(Observer player){ System.out.println(); System.out.println(MessageFormat.format("{0}退出{1}战队", player.getName(), this.allyName)); players.remove(player); } /** * 声明抽象通知方法 */ public abstract void notifyObserver(String name); }
具体目标类:ConcreteAllyControlCenter
https://github.com/Aro710/Game_mul/blob/master/observer/demo/ConcreteAllyControlCenter.java
public class ConcreteAllyControlCenter extends AllyControlCenter { public ConcreteAllyControlCenter(String allyName) { System.out.println(MessageFormat.format("{0}战队组件成功!", allyName)); System.out.println(); System.out.println("控制中心发布盟友召集令"); System.out.println("---------------------------------"); this.allyName = allyName; } @Override public void notifyObserver(String name) { System.out.println(); System.out.println(MessageFormat.format("{0}战队紧急通知:盟友{1}正在遭受攻击,请速速支援!", this.allyName, name)); System.out.println(); // 遍历观察者集合,调用每一个盟友(自己除外)的支援方法 for(Observer player : this.players){ if(!player.getName().equalsIgnoreCase(name)){ player.help(); } } } }
抽象观察者:Observer
https://github.com/Aro710/Game_mul/blob/master/observer/demo/Observer.java
public interface Observer { /** * 获取观察者名字 * @return */ String getName(); /** * 设置观察者名字 * @param name */ void setName(String name); /** * 声明支援盟友方法 */ void help(); /** * 声明遭受攻击方法 * @param acc */ void beAttacted(AllyControlCenter acc); }
具体观察者:Player
https://github.com/Aro710/Game_mul/blob/master/observer/demo/Player.java
public class Player implements Observer { private String name; public Player(String name) { this.name = name; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } /** * 支援盟友方法的实现 */ public void help() { System.out.println(MessageFormat.format("坚持住,{0}来救你!", this.name)); } /** * 遭受攻击方法的实现,当遭受攻击时将调用战队控制中心类的通知方法notifyObserver()来通知盟友 * @param acc */ public void beAttacted(AllyControlCenter acc) { System.out.println(); System.out.println(MessageFormat.format("{0}被攻击", this.name)); acc.notifyObserver(this.name); } }
观察者模式的优点如下:
(1) 观察者模式可以实现表示层和数据逻辑层的分离,定义了稳定的消息更新传递机制,并抽象了更新接口,使得可以有各种各样不同的表示层充当具体观察者角色。
(2) 观察者模式在观察目标和观察者之间建立一个抽象的耦合。观察目标只需要维持一个抽象观察者的集合,无须了解其具体观察者。由于观察目标和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。
(3) 观察者模式支持广播通信,观察目标会向所有已注册的观察者对象发送通知,简化了一对多系统设计的难度。
(4) 观察者模式满足“开闭原则”的要求,增加新的具体观察者无须修改原有系统代码,在具体观察者与观察目标之间不存在关联关系的情况下,增加新的观察目标也很方便。
原文地址:https://www.cnblogs.com/aro7/p/9848723.html