观察者模式

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。

介绍

意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

如何解决:使用面向对象技术,可以将这种依赖关系弱化。

应用实例:1.拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。
2.打团时每个职业做不同的事情。

优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。

缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

简单的说就是:多个对象去观察一个对象是否发出号令(消息),然后做出相应响应动作

以DNF打团为例子:
当团长发出攻坚开始的消息时所有的队友开始输出。

创建一个职业的抽象类(观察者接口):Hero

1
2
3
4
5
6
7
8
9
public abstract class Hero {

/**
* 打团
* @param msg
*/
public abstract void datuan(String msg);

}

分别创建三个职业(观察者)

创建一个红眼:Hongyan

1
2
3
4
5
6
7
8
9
public class Hongyan extends Hero {

private static final String ROLE = "帝血弑天";

@Override
public void datuan(String msg) {
System.out.println(msg+ ROLE +":血魔:弑天! ");
}
}

创建一个奶爸:Naiba

1
2
3
4
5
6
7
8
9
public class Naiba extends Hero {

private static final String ROLE = "神思者";

@Override
public void datuan(String msg) {
System.out.println(msg + ROLE + ": 阿波克列!");
}
}

创建一个篮拳:Lanquan

1
2
3
4
5
6
7
8
9
public class Lanquan extends Hero {

private static final String ROLE = "正义仲裁者";

@Override
public void datuan(String msg) {
System.out.println(msg+ ROLE + ":粉碎吧!");
}
}

创建一个团长(被观察者):Captain

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Captain {

private List<Hero> heroes = new ArrayList<>();

public void setMsg(String msg) {
notifyAll(msg);
}
//订阅
public void addTeam(Hero hero) {
heroes.add(hero);
}
//通知所有订阅的观察者
private void notifyAll(String msg) {
for (Hero observer : heroes) {
observer.datuan(msg);
}
}


}

主程序:Main

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Main {

public static void main(String[] args) {
Lanquan lanquan = new Lanquan();
Hongyan hongyan = new Hongyan();
Naiba naiba = new Naiba();

Captain captain = new Captain();
captain.addTeam(lanquan);
captain.addTeam(hongyan);
captain.addTeam(naiba);
captain.setMsg("超时空攻坚战开始-");

}

}

执行结果:

1
2
3
超时空攻坚战开始-正义仲裁者:粉碎吧!
超时空攻坚战开始-帝血弑天::血魔:弑天!
超时空攻坚战开始-神思者: 阿波克列!