观察者模式(Observer Pattern)
观察者模式又叫做订阅/发布模式
- 一个Subject,多Observer
- 相互之间持有引用
- Subject可以调用Observer的函数执行相应操作
- Observer发生变动时也可以通知Subject让其通知其他观察者。
给个小栗子(效果图如下)
目标被观察者
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package ObserverPattern; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 public abstract class Subject { 7 8 //define an ArrayList to store observers 9 private List<Observer> observers = new ArrayList<>(); 10 public List<Observer> getObservers() { 11 return observers; 12 } 13 14 15 public void join(Observer observer) { 16 observers.add(observer); 17 } 18 19 public void quit(Observer observer) { 20 observers.remove(observer); 21 } 22 23 public abstract void notifyObservers(String name); 24 25 }
观察者
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package ObserverPattern; public abstract class Observer { protected Subject subject; public Observer(Subject subject) { this.subject = subject; } public abstract void sysMsg(String msg); public abstract void beAttacked(); public abstract String getName(); public abstract void setName(String name); }
战况指挥中心
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package ObserverPattern; public class ActionControlCenter extends Subject { @Override public void notifyObservers(String name) { for (Observer observer : getObservers()) { if (name.equals(observer.getName())) observer.sysMsg(observer.getName() +"收到消息:坚持住,你队友正在赶来!"); else observer.sysMsg(observer.getName() +"收到消息:我方\"" + name + "\"正在受到攻击,请尽快支援!"); } } }
玩家
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package ObserverPattern; public class Player extends Observer { public Player(Subject subject) { super(subject); } private String name; public void setName(String name) { this.name = name; } public String getName() { return name; } @Override public void beAttacked() { System.out.println(getName() + "收到消息:您正在受到攻击!"); subject.notifyObservers(getName()); } @Override public void sysMsg(String msg) { System.out.println(msg); } }
测试用例
package ObserverPattern; import org.junit.Test; public class MainTest { @Test public void myTest() { ActionControlCenter controlCenter = new ActionControlCenter(); Player p1 = new Player(controlCenter); Player p2 = new Player(controlCenter); p1.setName("邓艾"); p2.setName("甄姬"); controlCenter.join(p1); controlCenter.join(p2); p2.beAttacked(); } }