观察者(Observer)模式又称为发布订阅模式(Publish/Subscribe),如果一个对象改变时需要通知其他对象,那么就可以用观察者模式解决。
一个简单的例子:顾客订阅了卖家,以后卖家有什么新消息(优惠活动、打折什么的)就可以找到并通知给顾客了:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
Seller seller = new Seller();
Customer tony = new Customer("Tony", seller);
Customer lisa = new Customer("Lisa", seller);
seller.attach(tony);
seller.attach(lisa);
seller.setNotifyText("薯条、薯片半价");
seller.send_notify();
}
}
//卖家(消息通知者)
class Seller {
private String notifyText;
private List<Customer> customerList = new ArrayList<>();
//添加顾客(消息订阅者)
public void attach(Customer customer){
customerList.add(customer);
}
//通知顾客最新消息
public void send_notify(){
for (Customer customer : customerList){
customer.update();
}
}
public String getNotifyText() {
return notifyText;
}
public void setNotifyText(String notifyText) {
this.notifyText = notifyText;
}
}
//顾客(消息订阅者)
class Customer {
private String name;
private Seller seller;
public Customer(String name, Seller seller) {
this.name = name;
this.seller = seller;
}
//得到通知时所采取的行动(这里只是简单地输出一下通知内容)
public void update(){
System.out.println(name + "收到通知:" + seller.getNotifyText());
}
}
Tony收到通知:薯条、薯片半价
Lisa收到通知:薯条、薯片半价
基本的观察者模式是这样了,不过现在卖家和顾客相互紧紧的耦合在一起了,也就是说顾客依赖于具体的卖家,卖家也需要知道具体的顾客,不符合依赖倒转原则,并且如果老板(另一种订阅者)也需要订阅卖家的消息,那么原来卖家的代码就需要修改了,这样也不符合开放-闭合原则,所以需要改良 解耦:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
Seller seller = new Seller();
Customer tony = new Customer("Tony", seller);
Customer lisa = new Customer("Lisa", seller);
seller.attach(tony);
seller.attach(lisa);
seller.setNotifyText("薯条、薯片半价");
seller.send_notify();
}
}
//卖家(消息通知者)
class Seller {
private String notifyText;
//把Customer改成Observer
private List<Observer> observerList = new ArrayList<>();
//添加顾客(消息订阅者)
public void attach(Observer observer){
observerList.add(observer);
}
//去除顾客(以后不再通知该顾客)
public void detach(Observer observer){
observerList.remove(observer);
}
//通知顾客最新消息
public void send_notify(){
for (Observer observer : observerList){
observer.update();
}
}
public String getNotifyText() {
return notifyText;
}
public void setNotifyText(String notifyText) {
this.notifyText = notifyText;
}
}
//抽象出一个观察者类(抽象消息订阅者)
abstract class Observer {
protected String name;
protected Seller seller;
public Observer(String name, Seller seller) {
this.name = name;
this.seller = seller;
}
abstract void update();
}
//顾客(具体消息订阅者)
class Customer extends Observer{
public Customer(String name, Seller seller) {
super(name, seller);
}
//得到通知时所采取的行动(这里只是简单地输出一下通知内容)
@Override
public void update(){
System.out.println(name + "收到通知:" + seller.getNotifyText());
}
}
通过依赖抽象类Observer,Seller类就不需要知道具体订阅消息的是谁了,但现在顾客依赖的仍然是具体的卖家,所以还需要改改:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
Subject seller = new Seller();
Observer tony = new Customer("Tony", seller);
Observer lisa = new Customer("Lisa", seller);
seller.attach(tony);
seller.attach(lisa);
seller.setSubjectState("薯条、薯片半价");
seller.send_notify();
}
}
//把消息发布者抽象成接口
interface Subject {
void attach(Observer observer);
void detach(Observer observer);
void send_notify();
String getSubjectState();
void setSubjectState(String subjectState);
}
//卖家(消息通知者)
class Seller implements Subject{
private String notifyText;
//把Customer改成Observer
private List<Observer> observerList = new ArrayList<>();
//添加顾客(消息订阅者)
@Override
public void attach(Observer observer){
observerList.add(observer);
}
//去除顾客(以后不再通知该顾客)
@Override
public void detach(Observer observer){
observerList.remove(observer);
}
//通知顾客最新消息
@Override
public void send_notify(){
for (Observer observer : observerList){
observer.update();
}
}
@Override
public String getSubjectState() {
return this.notifyText;
}
@Override
public void setSubjectState(String subjectState) {
this.notifyText = subjectState;
}
}
//抽象出一个观察者类(抽象消息订阅者)
abstract class Observer {
protected String name;
protected Subject subject;
public Observer(String name, Subject subject) {
this.name = name;
this.subject = subject;
}
abstract void update();
}
//顾客(具体消息订阅者)
class Customer extends Observer{
public Customer(String name, Subject subject) {
super(name, subject);
}
//得到通知时所采取的行动(这里只是简单地输出一下通知内容)
@Override
public void update(){
System.out.println(name + "收到通知:" + subject.getSubjectState());
}
}
最后,我把消息发布者也抽象成接口了