观察者模式(Observer Pattern)
又叫做发布订阅
两个角色:观察者和被观察者
两者存在“观察”的逻辑关联,当被观察者发生改变的时候,观察者就会观察到这样的变化,并且做出相应的响应,观察不是直接调用,实现观察者模式有很多形式,比较直观的一种是使用“注册——通知——撤销注册”的形式;
设计如下图:
具体代码如下:
//主题对象(被观察者)接口
public interface ISubject {
void registerObserver(Observer observer);//注册观察者
void removeObserver(Observer observer);//删除观察者
void notifyObserver();//通知观察者
}
//主题对象(被观察者)
public class Subject implements ISubject {
List<Observer> list = null;
private String message;
public Subject() {
this.list = new ArrayList<>();
}
@Override
public void registerObserver(Observer observer) {
list.add(observer);
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
notifyObserver();
}
@Override
public void removeObserver(Observer observer) {
list.remove(observer);
}
@Override
public void notifyObserver() {
for (int i = 0; i < list.size(); i++) {
list.get(i).update(message);
}
}
public List<Observer> getList() {
return list;
}
public void setList(List<Observer> list) {
this.list = list;
}
@Override
public String toString() {
return "Subject [list=" + list + ", message=" + message + "]";
}
}
//观察者接口
/***
* 依赖倒转原则
*
*/
public interface Observer {
void update(Object o);
}
//观察者对象
public class ConcreteObserver implements Observer {
private String name;
private String message;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public void update(Object o) {
this.message = (String) o;
}
}
//测试类
public class Test {
public class Test {
public static void main(String[] args) {
ConcreteObserver observer = new ConcreteObserver();
ConcreteObserver observer1 = new ConcreteObserver();
ConcreteObserver observer2 = new ConcreteObserver();
Subject subject = new Subject();
subject.registerObserver(observer);
subject.registerObserver(observer1);
subject.registerObserver(observer2);
subject.setMessage("111");
System.out.println(observer.getMessage());
subject.setMessage("222");
subject.removeObserver(observer1);
System.out.println(subject.list);
System.out.println(observer1.getMessage());
}
}
}
如上四个类,两个接口分别代表主题对象(被观察者)和观察者接口。
这里解释一下,主题对象即被观察者里面的方法,registerObserver 是注册观察者,因为观察者需要观察被观察者消息的变化,所以,在被观察者里面就需要一个集合来装观察者,以便当被观察者消息发生变化是及时通知到每一位观察者。removeObserver 是删除观察者,也就是说观察者可以选择放弃被观察者。还有一个notifyObserver通知观察者方法,是专门通知每一位观察者消息的。最后是观察者Observer对象中的update方法,主要是当被观察者通知消息时直接调用该方法。
之所以需要接口就是便于后期的扩展性。
但在这里发现一个问题:也就是说当观察者后期扩展时,每次都需要在观察者里面添加新的属性,在该例子中时message属性,如果有新的观察对象,那么会有新的观察属性,势必会在该观察者里面得添加一个新的属性,貌似违背了,设计理念中的开闭原则,怎么办呢?
希望看到的同行大牛给出新的一些建议,谢谢下方留言!