观察者模式
在对象之间定义一个一对多的关系,因此当一个对象状态改变,其它的关联对象(依赖它的)都被通知并且可以自动更新
概念
在这个模式中,存在很多观察者,它们在观察着同一个主题(对象)。当这个主题发生了改变,这些观察者希望被通知。因此,它们将自己注册到被观察的主题上,当它们不再对这个主题感兴趣,只要解除注册即可(也叫广播-接收模式)
例子
现实:粉丝和偶像之间的关系(粉丝是观察者,偶像是被关注的主题)
编程世界:UI和数据库的关系,数据库发生了数据变更之后,UI应该显示新的数据(自动更新)
展示
这里存在一个Observer,一个Subject,当subject的flag改变,observer会被通知,当observer不再关注这个主题,那么flag改变不会通知observer
Code
public class ObserverPattern {
public static void main(String[] args) {
Observer o1 = new Observer();
Subject sub1 = new Subject();
sub1.register(o1);
System.out.println("Setting Flag = 5 ");
sub1.setFlag(5);
System.out.println("Setting Flag = 25 ");
sub1.setFlag(25);
sub1.unregister(o1);
//No notification this time to o1 .Since it is unregistered.
System.out.println("Setting Flag = 50 ");
sub1.setFlag(50);
}
}
class Observer {
public void update() {
System.out.println("flag modified!");
}
}
interface ISubject {
void register(Observer observer);
void unregister(Observer observer);
void notifyAllObservers();
}
class Subject implements ISubject {
private List<Observer> observerList = new ArrayList<>(16);
private int flag;
public int getFlag() {
return flag;
}
public void setFlag(int flag) {
this.flag = flag;
notifyAllObservers();
}
@Override
public void register(Observer observer) {
observerList.add(observer);
}
@Override
public void unregister(Observer observer) {
observerList.remove(observer);
}
@Override
public void notifyAllObservers() {
for (Observer o: observerList) {
o.update();
}
}
}
改进
- 存在很多不同类的观察者
- 观察者想知道到底是什么发生了改变
UML图
代码改动
List<Observer> observerList = new ArrayList<Observer>();
// 接口来保证能接收不同类型的观察者
List<IObserver> observersList=new ArrayList<IObserver>();
全部代码:
public class ObserverPattern {
public static void main(String[] args) {
System.out.println("*** Modified Observer Pattern Demo***\n");
Subject sub = new Subject();
Observer1 ob1 = new Observer1();
Observer2 ob2 = new Observer2();
sub.register(ob1);
sub.register(ob2);
sub.setFlag(5);
System.out.println();
sub.setFlag(25);
System.out.println();
//unregister ob1 only
sub.unregister(ob1);
//Now only ob2 will observe the change
sub.setFlag(100);
}
}
class Observer1 implements IObserver {
@Override
public void update(int i) {
System.out.println("Observer1: myValue in Subject is now: "+i);
}
}
class Observer2 implements IObserver {
@Override
public void update(int i) {
System.out.println("Observer2: observes ->myValue is changed in Subject to :"+i);
}
}
interface ISubject {
void register(IObserver observer);
void unregister(IObserver observer);
void notifyAllObservers(int i);
}
interface IObserver {
void update(int i);
}
class Subject implements ISubject {
private List<IObserver> observerList = new ArrayList<>(16);
private int flag;
public int getFlag() {
return flag;
}
public void setFlag(int flag) {
this.flag = flag;
notifyAllObservers(this.flag);
}
@Override
public void register(IObserver observer) {
observerList.add(observer);
}
@Override
public void unregister(IObserver observer) {
observerList.remove(observer);
}
@Override
public void notifyAllObservers(int i) {
for (IObserver o: observerList) {
o.update(flag);
}
}
}
实现多个主题和多个观察者
自己做的:
思路:观察者模式的核心在于保有一个观察者列表,并且每个主题(类)的被关注值改变时通知列表中的所有观察者(对象)
假设:有三个观察者,两个主题
代码
public class ObserverPattern {
public static void main(String[] args) {
System.out.println("*** Modified Observer Pattern Demo***\n");
Subject1 sub1 = new Subject1();
SubJect2 sub2 = new SubJect2();
Observer1 ob1 = new Observer1();
Observer2 ob2 = new Observer2();
Observer2 ob3 = new Observer2();
sub1.register(ob1);
sub1.register(ob2);
sub2.register(ob1);
sub2.register(ob2);
sub2.register(ob3);
sub1.setFlag(5);
System.out.println();
sub1.setFlag(25);
System.out.println();
//unregister ob1 only
sub1.unregister(ob1);
//Now only ob2 will observe the change
System.out.println();
sub1.setFlag(100);
sub2.setFlag(4);
System.out.println();
sub2.setFlag(6);
}
}
class Observer1 implements IObserver {
@Override
public void update(int i) {
System.out.println("Observer1: myValue in Subject is now: "+i);
}
}
class Observer2 implements IObserver {
@Override
public void update(int i) {
System.out.println("Observer2: observes ->myValue is changed in Subject to :"+i);
}
}
interface ISubject {
void register(IObserver observer);
void unregister(IObserver observer);
void notifyAllObservers(int i);
}
interface IObserver {
void update(int i);
}
class Subject1 implements ISubject {
private List<IObserver> observerList = new ArrayList<>(16);
private int flag;
public int getFlag() {
return flag;
}
public void setFlag(int flag) {
this.flag = flag;
notifyAllObservers(this.flag);
}
@Override
public void register(IObserver observer) {
observerList.add(observer);
}
@Override
public void unregister(IObserver observer) {
observerList.remove(observer);
}
@Override
public void notifyAllObservers(int i) {
for (IObserver o: observerList) {
o.update(flag);
}
}
}
class SubJect2 implements ISubject {
private List<IObserver> observerList = new ArrayList<>(16);
private int flag;
public int getFlag() {
return flag;
}
public void setFlag(int flag) {
this.flag = flag;
notifyAllObservers(this.flag);
}
@Override
public void register(IObserver observer) {
observerList.add(observer);
}
@Override
public void unregister(IObserver observer) {
observerList.remove(observer);
}
@Override
public void notifyAllObservers(int i) {
for (IObserver o: observerList) {
o.update(flag);
}
}
}
代码很多都是重复的,只要把核心点掌握还是好写的
总结
观察者模式是天然实现广播功能的,如果一个对象的动作被多个对象监听,那么可以使用此设计模式。一般过程:
- 设计主题接口和观察者接口
- 具体实现类
- 在主题类的被监听属性的设置方法中要调用接口中声明的通知方法
- 如果观察者需要知道被改变的值,那么在观察者接口的
update
方法中设置参数
其它:观察者接口中的update
是观察者模式中体现主题改变的方法,即这个模式一般是观察者(对象)(可变化的)随主题(对象)的变化而变化