第14章 观察者模式
2020-04-07 本文已影响0人
小超_8b2f
1.双向耦合的代码
/**
* 前台秘书,消息统治者
*/
class Secretary {
//玩股票的同事的列表
private List<StockObserver> observers = new ArrayList<>();
//前台状态
private String action;
//增加观察者
public void add(StockObserver observer) {
observers.add(observer);
}
//通知所有有关联同事事情
public void Notify() {
for(StockObserver observer : observers) {
observer.update();
}
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
}
/**
* 股票观察者,玩股票的同事
*/
class StockObserver {
private String name;
private Secretary sub;
public StockObserver(String name, Secretary sub) {
this.name = name;
this.sub = sub;
}
public void update() {
//得到前台通知,赶快采取行动
System.out.println(sub.getAction() + "," + name + " 关闭股票行情,继续工作");
}
}
public class Client {
public static void main(String[] args) {
//前台小姐:通知者
Secretary notifier = new Secretary();
//看股票的同事
StockObserver tongshi1 = new StockObserver("张三", notifier);
StockObserver tongshi2 = new StockObserver("李四", notifier);
//前台记下了2位同事
notifier.add(tongshi1);
notifier.add(tongshi2);
//发现老板回来了
notifier.setAction("老板回来了");
notifier.Notify();
}
}
老板回来了,张三 关闭股票行情,继续工作
老板回来了,李四 关闭股票行情,继续工作
2. 解耦版一
问题:如果同事不光看股票呢?还有别 的行为咋办?将观察者抽象
abstract class Observer {
protected String name;
protected Secretary sub;
public Observer(String name, Secretary sub) {
this.name = name;
this.sub = sub;
}
public abstract void update();
}
//看股票行情的同事
class StockObserver extends Observer {
public StockObserver(String name, Secretary sub) {
super(name, sub);
}
@Override
public void update() {
System.out.println(sub.getAction() + "," + name + " 关闭股票行情,继续工作");
}
}
//看NBA直播的同事
class NBAObserver extends Observer {
public NBAObserver(String name, Secretary sub) {
super(name, sub);
}
@Override
public void update() {
System.out.println(sub.getAction() + "," + name + " 关闭NBA直播,继续工作");
}
}
//前台秘书
class Secretary {
//玩股票的同事的列表
private List<Observer> observers = new ArrayList<>();
//前台状态
private String action;
//增加观察者
public void add(Observer observer) {
observers.add(observer);
}
//减少观察者
public void detach(Observer observer) {
observers.remove(observer);
}
//前台秘书通知同事事情
public void Notify() {
for(Observer observer : observers) {
observer.update();
}
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
}
问题
通知者类解耦了观察者类,但是观察者类中依然耦合具体的统治者类。若是前台美女有事情了,她不通知你,咋办?
3. 解耦合版2
abstract class Notifier {
abstract void add(Observer observer);
abstract void remove(Observer observer);
abstract void Notify();
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
//老板
class Boss extends Notifier{
//玩股票的同事的列表
private List<Observer> observers = new ArrayList();
//增加观察者
@Override
public void add(Observer observer) {
observers.add(observer);
}
@Override
void remove(Observer observer) {
observers.remove(observer);
}
//老板通知同事事情
@Override
public void Notify() {
for(Observer observer : observers) {
observer.update();
}
}
}
//秘书
class Secretary1 extends Notifier{
//玩股票的同事的列表
private List<Observer> observers = new ArrayList();
//增加观察者
@Override
public void add(Observer observer) {
observers.add(observer);
}
@Override
void remove(Observer observer) {
observers.remove(observer);
}
//秘书通知同事事情
@Override
public void Notify() {
for(Observer observer : observers) {
observer.update();
}
}
}
/**
* 观察者抽象
*/
abstract class Observer {
protected String name;
protected Notifier notifier;
public Observer(String name, Notifier notifier) {
this.name = name;
this.notifier = notifier;
}
public abstract void update();
}
//看股票行情的同事
class StockObserver extends Observer {
public StockObserver(String name, Notifier notifier) {
super(name, notifier);
}
@Override
public void update() {
System.out.println(notifier.getState() + "," + name + " 关闭股票行情,继续工作");
}
}
//看NBA直播的同事
class NBAObserver extends Observer {
public NBAObserver(String name, Notifier notifier) {
super(name, notifier);
}
@Override
public void update() {
System.out.println(notifier.getState() + "," + name + " 关闭NBA直播,继续工作");
}
}
public class Test2 {
public static void main(String[] args) {
// Notifier boss = new Boss();
Notifier notifier = new Secretary1();
Observer stockObserver = new StockObserver("张三", notifier);
Observer NBAObserver = new NBAObserver("李四", notifier);
notifier.add(stockObserver);
notifier.add(NBAObserver);
// notifier.setState("我胡汉三回来了");
notifier.setState("我是前台美女小秘啊");
notifier.Notify();
}
}

观察者模式
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听一个主题对象。这个主题对象在状态发生变化的时候,会通知所有观察者对象,使它们能够自动更新自己。

/**
* 【主题】的抽象,观察者观察(订阅)这个【主题】
*/
public abstract class Subject {
private List<Observer> observers = new ArrayList();
//增加观察者
public void attach(Observer observer) {
observers.add(observer);
}
//移除观察者
public void detach(Observer observer) {
observers.remove(observer);
}
//通知
public void Notify() {
for(Observer o : observers) {
o.update();
}
}
}
/**
* 观察者抽象
*/
interface Observer {
void update();
}
/**
* 具体主题,或具体通知者,将有关状态存入具体主题对象;
* 在具体主题对象内部状态改变时,给所有登记过的观察者发出通知,
*/
@Data
class ConcreteSubject extends Subject {
private String subjectState;
}
/**
* 具体观察者角色可以指向一个具体的主题对象
*/
@Data
class ConcreteObserver implements Observer {
private String name;
private String observerState;
//具体观察者角色可以指向一个具体的主题对象,某种观察者只观察某种特定的主题
private ConcreteSubject subject;
public ConcreteObserver(ConcreteSubject subject,String name) {
this.subject = subject;
this.name = name;
}
@Override
public void update() {
observerState = subject.getSubjectState(); //使本身的状态与主题的状态相协调
System.out.println("观察者" + name + "的状态是:"+ observerState);
}
}
class Client {
public static void main(String[] args) {
ConcreteSubject s = new ConcreteSubject();
s.attach(new ConcreteObserver(s,"x"));
s.attach(new ConcreteObserver(s,"y"));
s.attach(new ConcreteObserver(s,"z"));
s.setSubjectState("ABC"); //主题状态发生变动
s.Notify(); //通知所有的观察者
}
}
观察者x的状态是:ABC
观察者y的状态是:ABC
观察者z的状态是:ABC
什么时候应该使用观察者模式?
当一个对象的改变需要同时改变其它对象的时候(而且它不知道具体有多少个对象有待改变)。
观察者总结
观察者模式所做的工作其实就是解耦合,让耦合的双方都依赖于抽象。而不是依赖于具体,从而使得各自的变化都不会影响另一边的变化。
依赖倒转的最佳体现。
观察者模式的不足
抽象通知者还是依赖抽象观察者,万一没有了抽象观察者这样的接口,通知功能就完不成了。
改进方案
通知者和观察者之间根本就互相不知道,由客户端来决定通知谁。