一、描述
当对象间存在一对多关系时,则适合使用观察者模式(Observer Pattern)。当一个对象的装态被改变时,则应该通知它的观察者对象,这就是观察者模式。
二、代码实现
被观察者类
public class Subject {
private int status;
private List<Observer> observers = new ArrayList<>();
/** 添加观察者对象 */
public void attach(Observer observer) {
this.observers.add(observer);
}
/** 通知所有观察者对象 */
public void notifyAllObservers() {
for (Observer observer : observers) {
observer.update();
}
}
/** 改变状态 */
public void setStatus(int status) {
//状态变化
this.status = status;
System.out.println("状态改变!");
//通知观察者
this.notifyAllObservers();
}
}
观察者抽象类
public abstract class Observer {
protected Subject subject;
public abstract void update();
}
观察者类
public class SubjectObserver extends Observer {
public SubjectObserver(Subject subject) {
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("被观察者对象subject状态发生变化!");
}
}
测试demo
public class Test {
public static void main(String[] args) {
Subject subject = new Subject();
SubjectObserver observer = new SubjectObserver(subject);
subject.setStatus(1);
}
}
运行结果
三、延伸思考-数据池(生产者与消费者)
生产者与消费者的关系在我们日常生活中非常的普遍,一家超市算是产品池(数据池),我们大众会去消费购买产品,属于消费者,当产品余量不足时会通知供货商发送新的产品过来,供货商就类似于生产者(当然这中间可能有中间商赚差价),一个生产与消费的关系边构建起来了。参考观察者模式,可以给数据池两个身份的观察者,一个是生产者,一个是消费者,代码如下:
数据池
public class DataPool<T> {
private BlockingQueue<T> dataPool ;
private final int MAX_SIZE;
//生产者
private DataPoolObserver producer;
//消费者
private DataPoolObserver consumer;
public DataPool(int MAX_SIZE) {
this.dataPool = new ArrayBlockingQueue<>(MAX_SIZE);
this.MAX_SIZE = MAX_SIZE;
}
/** 添加生产者 */
public void setProducer(DataPoolObserver producer) {
this.producer = producer;
}
/** 添加消费者 */
public void setConsumer(DataPoolObserver consumer) {
this.consumer = consumer;
}
/** 添加数据 */
public void add(T t) {
this.dataPool.add(t);
if (this.consumer != null) {
this.consumer.update();
}
}
/** 移除数据 */
public T get() {
//余量不足,通知生产者
if (this.dataPool.size() < 0.2 * this.MAX_SIZE && this.producer != null) {
this.producer.update();
}
if (this.dataPool.size() > 0) {
return this.dataPool.poll();
}
return null;
}
}
观察者抽象类
public abstract class DataPoolObserver<T> {
protected DataPool<T> dataPool;
public abstract void update();
}
生产者类
public class Producer extends DataPoolObserver<String> {
public Producer(DataPool<String> dataPool) {
this.dataPool = dataPool;
this.dataPool.setProducer(this);
}
/** 生产 */
public void run() {
System.out.println("生产了一个产品!");
this.dataPool.add("产品");
}
@Override
public void update() {
this.run();
}
}
消费者类
public class Consumer extends DataPoolObserver<String> {
public Consumer(DataPool<String> dataPool) {
this.dataPool = dataPool;
this.dataPool.setConsumer(this);
}
/** 消费 */
public void run() {
System.out.println("消费了一个产品!");
this.dataPool.get();
}
@Override
public void update() {
run();
}
}
测试类
public class Test {
public static void main(String[] args) {
DataPool<String> dataPool = new DataPool<>(20);
Producer producer = new Producer(dataPool);
observerPattern.Consumer consumer = new observerPattern.Consumer(dataPool);
producer.run();
}
}
运行结果
这样就实现了一个生产与消费的关系,如果生产者和消费者都实现Runnable接口,就可以使用线程实现异步的生产和消费关系,更加灵活。这样的设计可以给数据传输处理提供便利。