观察者模式
有两组实体对象,一组是观察者,一组是被观察者。Concretesubject是被观察者,ConcreteObserver是观察者。所有的观察者,都实现了Observer接口;所有的被观察者,都继承自Subject抽象类。
听着有点懵逼,直接上代码
定义一个观察者接口
//观察者
public interface Observer {
public void update();
}
定义被观察者抽象类
//被观察者
abstract class Subject {
//内部维护的一个观察者列表
private List<Observer> observerList = new ArrayList<Observer>();
//添加观察者
public void attachObserver(Observer observer) {
observerList.add(observer);
}
//移除观察者
public void detachObserver(Observer observer) {
observerList.remove(observer);
}
//通知观察者
public void notifyObservers() {
for (Observer observer : observerList) {
observer.update();
}
}
}
怪物、宝物、陷阱观察者
//怪物观察者
public class Monster implements Observer {
@Override
public void update() {
if (inRange()) {
System.out.println("怪物对主角进行攻击!");
}
}
private boolean inRange() {
//判断主角是否在自己的影响范围内,这里忽略细节,直接返回true
return true;
}
}
//陷阱观察者
public class Trap implements Observer {
@Override
public void update() {
if (inRange()) {
System.out.println("陷阱 困住主角!");
}
}
private boolean inRange() {
// 判断主角是否在自己的影响范围内,这里忽略细节,直接返回true
return true;
}
}
//宝物观察者
public class Treasure implements Observer {
@Override
public void update() {
if (inRange()) {
System.out.println("宝物 为主角加血!");
}
}
private boolean inRange() {
// 判断主角是否在自己的影响范围内,这里忽略细节,直接返回true
return true;
}
}
每一个观察者都实现了自己不同的update方法。分别对观察者有不同的处理方法。
创建主角类,他是被观察的对象,主教类做出操作,这时候就调用notifyObServers()方法来进行通知观察者,观察者分别调用自己的update()方法。
//被观察者
public class Hero extends Subject{
void move() {
System.out.println("主角向前移动");
//触发操作,遍历通知观察者
notifyObservers();
}
}
以下是测试类
public static void main(String[] args) {
//初始化对象
Hero hero = new Hero();
Monster monster = new Monster();
Trap trap = new Trap();
Treasure treasure = new Treasure();
//注册观察者
hero.attachObserver(monster);
hero.attachObserver(trap);
hero.attachObserver(treasure);
//移动事件
hero.move();
}
}
结果:
主角向前移动
怪物对主角进行攻击!
陷阱 困住主角!
宝物 为主角加血!
我们可以看到只要hero触发move,其他观察者对象都做出了反应。
什么时候用观察者模式呢?
当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象有待改变的时候,应该考虑使用观察者模式。
而使用观察者模式的动机在于:将一个系统分割成一系列相互协作的类有一个很不好的副作用,就是需要维护相关对象间的一致性,我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便,而观察者模式所做的工作就是在解除耦合。
应用实例:
- 手机丢了,委托别人给其他人发消息通知
- 通知老师/老板来了
- 拍卖,拍卖师观察最高标价,然后通知给其它竞价者竞价
- 在一个目录下建立一个文件,会同时通知目录管理器增加目录,并通知磁盘减少空间,文件是被观察者,目录管理器和磁盘管理器是观察者
- 猫叫了一声,吓着了老鼠,也惊到了主人,猫是被观察者,老鼠和人是观察者。
注意事项:
- 避免循环引用
- 如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。
本文来自博客园,作者:程序员hg,转载请注明原文链接:https://www.cnblogs.com/hg-blogs/p/16038335.html