观察者模式
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新
观察者模式就两种角色,一是观察者,二是被观察者( 主题 ),也可以认为是订阅者和发布者。
收通知的就是观察者。
如果观察者和被观察者这几个字已被混淆,可以用报纸发布订阅来套。客户是订阅报纸,收报纸的人( 收通知 ),所以客户就是观察者,那么报社就是被观察者了。
使用
/**
* 抽象类
* @author aodeng-低调小熊猫
* @since 19-7-15
*/
public abstract class Customer {
/**
* <p>
* 定义一个抽象方法
* </p>
* @author aodeng
* @since 19-7-15
*/
public abstract void update();
}
/**
* 收到通知的观察者客户A
* @author aodeng-低调小熊猫
* @since 19-7-15
*/
public class CustomerA extends Customer {
@Override
public void update() {
System.out.println("我是客户A,我收到报纸了!");
}
}
/**
* 收到通知的观察者客户B
* @author aodeng-低调小熊猫
* @since 19-7-15
*/
public class CustomerB extends Customer {
@Override
public void update() {
System.out.println("我是客户B,我收到报纸了");
}
}
/**
* 被观察者 报社
* @author aodeng-低调小熊猫
* @since 19-7-15
*/
public class NewsOffice {
private List<Customer> customerList=new ArrayList<>();
public void add(Customer customer){
this.customerList.add(customer);
}
/**
* <p>
* 模拟新报纸来了
* </p>
* @author aodeng
* @since 19-7-15
*/
public void newspaperCome(){
this.notifyAllObservers();
}
public void notifyAllObservers(){
for (Customer customer : customerList) {
customer.update();
}
}
}
测试
public static void main(String[] args) {
System.out.println("Hello World!");
NewsOffice newsOffice=new NewsOffice();
newsOffice.add(new CustomerA());
newsOffice.add(new CustomerB());
newsOffice.newspaperCome();
}
输出:
Hello World!
我是客户A,我收到报纸了!
我是客户B,我收到报纸了
加强
/**
* 定义被观察者接口
* @author aodeng-低调小熊猫
* @since 19-7-15
*/
public interface ISubject {
public void registerObserver(Customer customer);
public void removeObserver(Customer customer);
public void notifyObservers();
}
/**被观察者 报社 加强版
* @author aodeng-低调小熊猫
* @since 19-7-15
*/
public class NewsOfficeNiu implements ISubject {
private List<Customer> customerList = new ArrayList<>();
@Override
public void registerObserver(Customer customer) {
this.customerList.add(customer);
}
@Override
public void removeObserver(Customer customer) {
customerList.remove(customer);
}
@Override
public void notifyObservers() {
for (Customer customer : customerList) {
customer.update();
}
}
//模拟报纸来了
public void newspaperCome(){
this.notifyObservers();
}
}
测试
System.out.println("加强版========");
ISubject iSubject=new NewsOfficeNiu();
Customer customera=new CustomerA();
iSubject.registerObserver(customera);
iSubject.removeObserver(customera);
iSubject.registerObserver(new CustomerB());
((NewsOfficeNiu) iSubject).newspaperCome();
输出:
加强版========
我是客户B,我收到报纸了
Java 提供的观察者模式
Java 已经为我们提供观察者模式所需要的类:Observer 类和 Subject 类,只不过在 Java 中 Subject 不叫 Subject,而叫 Observable。
copy 一个demo
//demo
public class NewsOffice2 extends Observable {
/**
* 模拟报纸来了
*/
public void newspaperCome(){
this.setChanged();
this.notifyObservers();
}
}
public class CustomerC implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("我是客户C,我收到消息啦");
}
}
//测试
Observableoffice = new NewsOffice2();
Observer observer = new CustomerC();
office.addObserver(observer);
((NewsOffice2) office).newspaperCome();
总结
java自带的考虑到了线程安全,但是自己写的很多时候比较方便,有利有弊
1.优点
观察者和被观察者之间抽象耦合,自有一套触发机制,被观察者无需知道通知对象是谁,只要是符合观察者接口的就可以。
2.缺点
观察者只知道被观察者发生变化,而无法知道是如何发生变化的,比如是修改了 name 字段还是其他,观察者都不知道。
如果有很多个观察者,一个个通知比较耗时。
源码
Links:
本文由低调小熊猫一文多发操作发布! 欢迎关注公众号:低调小熊猫