1 基本介绍
观察者模式是使用频率最高的设计模式之一。
基本是:定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。
别名又称为发布-订阅模式,模型-视图模式,源-监听者模式
2 设计分析
使用观察者模式来进行多人联机对战游戏的设计
2.1 栗子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
| package DesignPatterns.JavaDesign.Observer;
import java.util.ArrayList;
public class Test { 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); } }
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; }
@Override public String getName() { return name; }
@Override public void setName(String name) { this.name = name; }
@Override public void help() { System.out.println("坚持住," + this.name + "来救你"); }
@Override 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 String getAllyName() { return allyName; }
public void setAllyName(String allyName) { this.allyName = 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; }
@Override public void notifyObserver(String name) { System.out.println(this.allyName + "战队紧急通知,盟友" + name); for (Observer player : players) { if (!((Observer)player).getName().equalsIgnoreCase(name)) { ((Observer)player).help(); } } } }
|
在本例中,实现了两次对象之间的联动,当一个游戏玩家Player
对象的beAttacked()
方法被调用时,将调用AllyControlCenter
的notifyObserver()
方法来进行处理,而在notifyObserver()
方法中又将调用其他Player对象的help()
方法。
Player.beAttacked() –> AllyControlCenter.notifyObserver() –>Player
3 总结
优缺点分析
优点:
- 实现表示层和数据逻辑层的分离,定义了稳定的消息更新传递机制
- 观察者模式在观察目标和观察者之间建立一个抽象的耦合。
- 观察者模式支持广播通信,观察目标会向所有已注册的观察者对象发送通知,简化了一对多系统设计的难度。
- 观察者模式满足“开闭原则”的要求,增加新的具体观察者无须修改原有系统代码
缺点:
- 如果一个观察目标对象有很多直接和间接观察者,将所有的观察者都通知到会花费很多时间
- 如果在观察者和观察目标之间存在循环依赖,观察目标会触发它们之间进行循环调用,可能导致系统崩溃
- 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
4 场景使用
4.1 Spring中ApplicationContext的使用
ApplicationContext
事件机制是观察者设计模式的实现,通过 ApplicationEvent
类和 ApplicationListener
接口,可以实现 ApplicationContext
事件处理。 如果容器中有一个 ApplicationListener Bean ,每当 ApplicationContext 发布 ApplicationEvent 时,ApplicationListener Bean 将自动被触发。这种事件机制都必须需要程序显示的触发。
ApplicationContext事件监听
当ApplicationContext内的Bean对象初始化完成时,此时可以通过监听 ContextRefreshedEvent 得到通知
将对象添加到容器中
参考
(111条消息) 设计模式之Spring中观察者模式_字节跳动的博客-CSDN博客_spring中的观察者模式