观察者模式是java设计是java设计模式里面比较常用的模式,最近在看springCould,拿出来熟悉一下。
观察者模式在对象之间存在一对多关系时使用,例如,如果一个对象被修改,它的依赖对象将被自动通知。 观察者模式属于行为模式类别。(注意,对象被修改的时候,在通知的过程中,我们要考虑是否会受到多线程的影响,观察者模式如果使用普通java类是线程不安全的)。
代码来一波:
首先创建一个subject对象类,这个类是被观察的对象
public class Subject {
private List<Observer> observers= new ArrayList<Observer>();
/**
* volatile无法保证原子性,只能保证可见性
*/
// private volatile int state;
private AtomicInteger state=new AtomicInteger();
public int getState() {
return state.get();
}
public void setState(int state) {
this.state.set(state);
notifyAllObservers();
}
public void attach(Observer observer){
observers.add(observer);
}
private void notifyAllObservers() {
for (Observer observer : observers) {
observer.update();
}
}
}
然后创建一个观察者
public abstract class Observer {
protected Subject subject;
public abstract void update();
}
创建三个方法,继承观察者
public class BinaryObserver extends Observer {
public BinaryObserver(Subject subject) {
this.subject=subject;
this.subject.attach(this);
}
/**
* 应该会有线程安全的问题,比如通知其他对象更新的 时候出现修改,会出现不一致的情况
*/
@Override
public void update() {
System.out.println("Binnary String:" +Integer.toBinaryString(subject.getState()));
}
}
public class HexaObserver extends Observer {
public HexaObserver(Subject subject) {
this.subject=subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("Hex String"+Integer.toHexString(subject.getState()));
}
}
public class OctalObserver extends Observer {
public OctalObserver(Subject subject) {
this.subject=subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("Octal String"+Integer.toOctalString(subject.getState()));
}
}
主类:
public class ObserverPatternDemo {
public static void main(String[] args) {
Subject subject = new Subject();
AtomicInteger atomicInteger = new AtomicInteger();
new HexaObserver(subject);
new OctalObserver(subject);
new BinaryObserver(subject);
new Thread(()->{
System.out.println("First state change 15");
subject.setState(15);
}).start();
new Thread(()->{
System.out.println("Second state change 10");
subject.setState(10);
}).start();
System.out.println(subject.toString());
}
}
这里使用多线程是因为使用单线程的时候考虑到线程安全问题,测试一波,有兴趣的可以单线程试试。
测试结果;
First state change 15
com.dmall.demoweb.Model.ObserverModel.Subject@25f38edc
Hex Stringf
Octal String17
Binnary String:1111
Second state change 10
Hex Stringa
Octal String12
Binnary String:1010