观察者
记得以前有个超火的游戏叫做传奇,小时候经常逃学和同学去玩传奇打boss。
经常一群人围着一个boss打,boss往哪边走,相应位置的人停止攻击就跑。
这就是最基本观察模式了用代码来实现就是:
class Hierarch{
//boss名字
private String name;
//boss状态
private String state;
private Zhangsan zs;
private Lisi ls;
public Hierarch(String name){
this.name=name;
}
//加入打boss的玩家
public void addPlayer(Zhangsan zs,Lisi ls){
this.zs=zs;
this.ls=ls;
}
public void walk(String state){
this.state=state;
zs.receive(this);
ls.receive(this);
}
public String getState(){return state;}
public String getName(){return name;}
}
class Zhangsan{
//接受boss信息
public void receive(Hierarch boss){
System.out.println(boss.getName()+boss.getState()+"张三赶紧停下让李四拉仇恨");
}
}
class Lisi{
public void receive(Hierarch boss){
System.out.println(boss.getName()+boss.getState()+"李四一看不是自己的仇恨抓紧时间攻击");
}
}
public class Client {
public static void main(String[] args) {
Hierarch boss=new Hierarch("沃玛教主");
Zhangsan zs=new Zhangsan();
Lisi ls=new Lisi();
boss.addPlayer(zs, ls);
boss.walk("往张三去了");
}
}
输出
沃玛教主往张三去了张三赶紧停下让李四拉仇恨
沃玛教主往张三去了李四一看不是自己的仇恨抓紧时间攻击
这样两个人时时观察boss就不怕被boss打到了,但是这样boss和玩家,你中有我,我中有你的双耦合模式,不符合依赖倒置。如果突然王五也逃学过来要一起打boss了,又要修改boss类不符合开闭原则。
所以遵循依赖导和开闭原则后致后:
class Hierarch{
private String name;
private String state;
//直接依赖玩家接口,来一个加一个就好
private List<Player> list=new ArrayList<Player>();
public Hierarch(String name){
this.name=name;
}
public void addPlayer(Player player ){
list.add(player);
}
public void walk(String state){
this.state=state;
for(Player player:list){
player.receive(this);
}
}
public String getState(){return state;}
public String getName(){return name;}
}
//做一个玩家接口直接让所有玩家实现
interface Player{
void receive(Hierarch boss);
}
这样结果没有变,但是增加修改就变成更加容易了。
同样的如过打完沃玛教主要打牛魔王了,总不能又去修改玩家的观察目标把,所以抽象又来了
abstract class Boss{
private String name;
private String state;
private List<Player> list=new ArrayList<Player>();
public Boss(String name){
this.name=name;
}
public void addPlayer(Player player ){
list.add(player);
}
public abstract void walk(String state);
public String getState(){return state;}
public String getName(){return name;}
public List<Player> getList() {return list;}
public void setList(List<Player> list) {this.list = list;}
public void setName(String name) {this.name = name;}
public void setState(String state) {this.state = state;}
}
class Bull extends Boss{
public Hierarch(String name) {
super(name);
}
@Override
public void walk(String state) {
setState(state);
for(Player player:getList()){
player.receive(this);
}
}
}
interface Player{
void receive(Boss boss);
}
class Zhangsan implements Player{
public void receive(Boss boss){
System.out.println(boss.getName()+boss.getState()+"张三赶紧停下让李四拉仇恨");
}
}
class Lisi implements Player{
public void receive(Boss boss){
System.out.println(boss.getName()+boss.getState()+"李四一看不是自己的仇恨抓紧时间攻击");
}
}
public class Client {
public static void main(String[] args) {
Bullboss=new Bull("牛魔王");
Zhangsan zs=new Zhangsan();
Lisi ls=new Lisi();
boss.addPlayer(ls);
boss.addPlayer(zs);
boss.walk("往张三去了");
}
}
这样就相互都可以随意换目标了。
观察者模式组成、
目标(Subject): 他把所有对观察者对戏的引用保存在一个聚集里,每一个主题都可以有多个观察者。(Boss)
观察者(Observer):为所有的具体观察者定义一个接口,在得到主题的通知时能够及时的更新自己。(玩家接口)
具体观察者(ConcreteObserver):实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态相协调。(张三等实际玩家)
具体主题(ConcreteSubject):将有关状态存入具体观察者对象。在具体主题发生改变时,给所有的观察者发出通知。
UML
观察者模式就记住两点
为了解耦
当目标状态发生变化时,会通知所有观察者,使他们能够更新自己。
以上就是我对观察者的理解,有错误可以指出。