观察者模式
定义:观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有的观察者对象,使它们能够自动更新自己。
UML图
代码
/**
* @className:ISubject
* @Description: 抽象类
* @Date:2018/11/4 23:12
*/
public interface ISubject {
/**
* 增加观察者
* */
void attach(Observer observer);
/**
* 减少观察者
* */
void detach(Observer observer);
/**
* 通知状态进行改变
* */
void notifyObserver();
}
/**
* @className:Observer
* @Description:被观察者
* @Date:2018/11/4 23:13
*/
abstract class Observer {
protected String name;
protected ISubject sub;
public String getName() {
return name;
}
public Observer(String name, ISubject sub) {
this.name = name;
this.sub = sub;
}
/**
* 更新被观察者的状态
* */
public abstract void update();
}
/**
* @className:Boss
* @Description: 具体的通知者
* @Date:2018/11/4 23:18
*/
public class Boss implements ISubject{
private List<Observer> observers=new ArrayList<>();
private String action;
/**
* 获取老板的状态
* */
public String getAction() {
return action;
}
/**
* 改变老板的状态
* */
public void setAction(String action) {
this.action = action;
}
@Override
public void attach(Observer observer) {
observers.add(observer);
}
@Override
public void detach(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObserver() {
for(Observer observer:observers){
observer.update();
}
}
}
/**
* @className:Secretary
* @Description: 秘书,和老板一样,具有通知的作用,代码与boss一致
* @Date:2018/11/4 23:24
*/
public class Secretary implements ISubject{
@Override
public void attach(Observer observer) {
}
@Override
public void detach(Observer observer) {
}
@Override
public void notifyObserver() {
}
}
/**
* @className:NBAObserver
* @Description:
* @Date:2018/11/4 23:35
*/
public class NBAObserver extends Observer{
String name;
public NBAObserver(String name, ISubject sub) {
super(name, sub);
this.name=name;
}
@Override
public void update() {
System.out.println(name+"关闭NBA直播,继续工作");
}
}
/**
* @className:StockObserver
* @Description:
* @Date:2018/11/4 23:27
*/
public class StockObserver extends Observer {
String name;
public StockObserver(String name, ISubject sub) {
super(name, sub);
this.name=name;
}
@Override
public void update() {
System.out.println(name+"关闭股票行情,继续工作");
}
}
public class Client{
public static void main(String[] args) {
Boss huhansa=new Boss();
StockObserver stockObserver=new StockObserver("魏关姹",huhansa);
NBAObserver nbaObserver=new NBAObserver("易管查",huhansa);
huhansa.attach(stockObserver);
huhansa.attach(nbaObserver);
/**
* 假设两个人被老板抓住了
* */
huhansa.notifyObserver();
/**
* 若只是一个人被抓住了,那么先要删除一个observer
* */
huhansa.detach(nbaObserver);
huhansan.notifyObserver();
}
}
Problem
在这个实例中,仔细观察之下,‘’抽象通知者‘’还是依赖"抽象观察者",即万一没有了抽象观察者这样的接口,那么通知的功能就不可用了。
在这个需求下面,由于‘’抽象通知者‘’不想依赖"抽象观察者",那么增加(add)和减少(detach)方法就不需要再继续存在了。
事件委托
委托是一种引用方法的类型,一旦为委托分配了方法,委托将于该方法具有完全相同的行为,委托方法的使用可以向其他任何方法一样,具有参数和返回值。委托可以看做是对函数的抽象,是函数的“类”,委托的实例将代表一个具体的函数。
事件委托,解决问题:一个委托可以搭载多个方法,所有方法被一次唤起。更重要的是委托可以使得委托对象所搭载的方法并不需要属于同一个类,这样我们就可以解开本来通知者与抽象观察者的耦合。
委托依赖于动态的绑定过程,它可以要求特定的方法可以在运行的时候调用不同的代码段。
接下来我们使用另外一个具体的demo来分析事件委托:
一个班级,有两类学生,A类:不学习,玩,但是玩的东西不一样,有的是做游戏,有的是看电视
B类:放哨的学生,专门看老师的动向,如果老师进班了就立即通知大家。
需求:当有老师来了的时候,那么B类的学生立马通知A类的学生,不管他们是在看电视还是在做游戏。设计的要求如下,让A类学生和B类学生完全解耦,即B类完全不知道A类的学生,却可以通知A类的学生。
参考URL:https://blog.csdn.net/qiumuxia0921/article/details/52067604
小结
当一个对象的改变需要同时改变其他对象的时候,我们需要考虑使用观察者模式,而且它不知道具体有多少个对象有待改变的时候,也应该适应观察者模式。观察者模式所做的工作就是解出耦合,让耦合的双方都依赖于抽象而不是依赖于具体,从而使得各自的变化不会影响另外一边的变化。虽然在实际过程中,观察者模式存在一定的缺陷,但是增加了事件委托这个特性之后,观察者模式就是比较完美的了。从代码中可以看到,事件委托的实现是基于简单的反射的。