观察者模式又称为发布订阅模式,是对象的行为模式。
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监视着被观察者的状态,当被观察者的状态发生变化时,会通知所有观察者,并让其自动更新自己。
观察者模式更易于扩展,责任也更加清晰。首先,把每一个电商接口看成一个观察者,每一个观察者都能观察到产品列表(被监听对象)。当公司发布新产品时,就会发送到这个产品列表上,于是产品列表(被监听对象)就发生了变化,这时就可以触发各个电商接口(观察者)发送新产品到对应的合作电商那里,观察者模式示例如图所示。
类似这样,一个对象(电商接口)会去监听另外一个对象(产品列表),当被监听对象(产品列表)发生变化时,对象(电商接口)就会触发一定的行为,以适合变化的逻辑模式,我们称为观察者模式,电商接口被称为观察者或者监听者,而产品对象被称为被观察者或者被监听者。
观察者模式要同时存在观察者和被观察者双方,观察者可以是多个。在Java中,需要去继承 java.util.Observable类,先看被观察者——一个产品列表,代码如下
package com.learn.observer;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
public class ProductList extends Observable {
/**
* 产品列表
* */
private List<String> productList=null;
/**
* 类唯一实例
* */
private static ProductList instance;
/**
* 构建方法私有化
*/
private ProductList(){}
/**
* 取得唯一实例
* @return 产品列表唯一实例
*/
public static ProductList getInstance(){
if(instance==null){
instance=new ProductList();
instance.productList=new ArrayList<String>();
}
return instance;
}
/**
* 增加观察者(电商接口)
* @param observer 观察者
*/
public void addProductListObserver(Observer observer){
this.addObserver(observer);
}
/**
* 新增产品
* @param newProduct 新产品
*/
public void addProduct(String newProduct){
productList.add(newProduct);
System.out.println("产品列表新增了产品:"+newProduct);
//设置被观察对象发生变化
this.setChanged();
//通知观察者并传递新产品
this.notifyObservers(newProduct);
}
}
这个类的一些基本内容和主要方法如下:
- ·构建方法私有化,避免通过new的方式创建对象,而是通过 getlnstance方法获得产品列表单例,这里便用的是单例模式。
- ·addProductListObserver可以增加一个电商接口(观察者)。
- ·核心逻辑在addProduct 方法上。在产品列表上增加了一个新的产品,然后调用setChanged方法。这个方法用于告知观察者当前被观察者发生了变化,如果没有,则无法触发其行为。最后通过notifyObservers告知观察者,让它们发生相应的动作,并将新产品作为参数传递给观察者。
这时已经有了被观察者对象,还要去编写观察者。仍以淘宝和京东为例,去实现它们的电商接口。作为观察者需要实现java.util.Observer接口的update方法,代码如下
package com.learn.observer;
import java.util.Observable;
import java.util.Observer;
/**
* 京东电商接口
*/
public class JinDongObserver implements Observer {
@Override
public void update(Observable o, Object product) {
String newProduct=(String)product;
System.out.println("发送新产品:【"+newProduct+"】同步到京东商城");
}
}
package com.learn.observer;
import java.util.Observable;
import java.util.Observer;
/**
* 淘宝电商接口
*/
public class TaoBaoObserver implements Observer {
@Override
public void update(Observable o, Object product) {
String newProduct= (String) product;
System.out.println("发送新产品:【"+newProduct+"】同步到淘宝商城");
}
}
测试一下这两个观察者和产品列表的被观察者
package com.learn.observer;
public class Test {
public static void main(String[] args) {
ProductList observable=ProductList.getInstance();
TaoBaoObserver taoBaoObserver=new TaoBaoObserver();
JinDongObserver jinDongObserver=new JinDongObserver();
observable.addObserver(jinDongObserver);
observable.addObserver(taoBaoObserver);
observable.addProduct("新增产品1");
}
}
以后在产品列表发布新产品,观察者们都可以触发对应的行为。
Java标准库有个java.util.Observable
类和一个Observer
接口,用来帮助我们实现观察者模式。但是,这个类非常不!好!用!实现观察者模式的时候,可以不借助这两个东东。
观察者模式(Observer)又称发布-订阅模式(Publish-Subscribe:Pub/Sub)。它是一种通知机制,让发送通知的一方(被观察方)和接收通知的一方(观察者)能彼此分离,互不影响。
假设一个电商网站,有多种Product
(商品),同时,Customer
(消费者)和Admin
(管理员)对商品上架、价格改变都感兴趣,希望能第一时间获得通知。
package com.learn.observer2;
public class Product {
private String name;
private double price;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
public void setName(String name) {
this.name = name;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Product{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
package com.learn.observer2;
public interface ProductObserver {
void onPublished(Product product);
void onPriceChanged(Product product);
}
package com.learn.observer2;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Store {
private List<ProductObserver> observers=new ArrayList<>();
private Map<String,Product> products=new HashMap<>();
public void addObserver(ProductObserver observer){
this.observers.add(observer);
}
public void removeObserver(ProductObserver observer){
this.observers.remove(observer);
}
public void addNewProduct(String name,double price){
Product p=new Product(name,price);
products.put(p.getName(),p);
observers.forEach(o ->o.onPublished(p));
}
public void setProductPrice(String name,double price){
Product p=products.get(name);
p.setPrice(price);
observers.forEach(o->o.onPriceChanged(p));
}
}
package com.learn.observer2;
class Customer implements ProductObserver{
@Override
public void onPublished(Product product) {
System.out.println("[Customer] on product published:"+product);
}
@Override
public void onPriceChanged(Product product) {
System.out.println("[Customer] on product price changed:"+product);
}
}
class Admin implements ProductObserver{
@Override
public void onPublished(Product product) {
System.out.println("[Admin] on product published:"+product);
}
@Override
public void onPriceChanged(Product product) {
System.out.println("[admin] on product price changed:"+product);
}
}
public class Test {
public static void main(String[] args) {
//observer:
Admin admin=new Admin();
Customer customer=new Customer();
//store
Store store=new Store();
//register:
store.addObserver(admin);
store.addObserver(customer);
//注册匿名观察者
store.addObserver(new ProductObserver() {
@Override
public void onPublished(Product product) {
System.out.println("[log] on product published:"+product);
}
@Override
public void onPriceChanged(Product product) {
System.out.println("[log] on product price changed:"+product);
}
});
//operation
store.addNewProduct("Design Patterns",88.88);
store.addNewProduct("Effective",99.99);
store.setProductPrice("Design Patterns",66.66);
}
}
测试结果如下