大话设计模式

第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();
    }
}
image.png

观察者模式

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

观察者模式结构图
/**
 * 【主题】的抽象,观察者观察(订阅)这个【主题】
 */
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

什么时候应该使用观察者模式?

当一个对象的改变需要同时改变其它对象的时候(而且它不知道具体有多少个对象有待改变)。

观察者总结

观察者模式所做的工作其实就是解耦合,让耦合的双方都依赖于抽象。而不是依赖于具体,从而使得各自的变化都不会影响另一边的变化。
依赖倒转的最佳体现。

观察者模式的不足

抽象通知者还是依赖抽象观察者,万一没有了抽象观察者这样的接口,通知功能就完不成了。

改进方案

通知者和观察者之间根本就互相不知道,由客户端来决定通知谁。

上一篇 下一篇

猜你喜欢

热点阅读