设计模式——观察者模式

场景一:
老板出门回来的时候,前台秘书给大家打电话,大家马上各就各位,这样就不会被老板发现问题。
第一版代码(双向耦合)
前台秘书类:

package observer1;
import java.util.*;
public class secretary {
    private List<observer> observers = new ArrayList<>();
    private String action;
    public void attach(observer o) {
        //有几个同事请前台帮忙,就给集合增加几个对象
        observers.add(o);
    }
    public void notity() {
        for (observer o : observers) {
            //给所有同事发通知
            o.update();
        }
    }
    public String getAction() {
        return action;
    }
    public void setAction(String action) {
        this.action = action;
    }
}

看股票同事类:

package observer1;
public class observer {
    private String name;
    //秘书对象
    private secretary s;

    public observer(String name, secretary s) {
        this.name = name;
        this.s = s;
    }
    public void update(){
        String format = String.format("%s,%s关闭股票,继续工作",s.getAction(),name);
        System.out.println(format);
    }
}

客户端:

package observer1;
public class client {
    public static void main(String[] args) {
        //前台秘书
        secretary s = new secretary();
        //看股票的两个同事
        observer tongshi1 = new observer("zyy",s);
        observer tongshi2 = new observer("yan",s);
        s.attach(tongshi1);
        s.attach(tongshi2);
        //老板回来了
        s.setAction("老板回来了");
        //通知同事
        s.notity();
    }
}

在这里插入图片描述

但是两个类之间互相耦合,前台类要增加观察者,观察者类需要前台的状态,如果需要添加看NBA直播的同事,还需要改动前台类,违背了以下设计原则:

  1. 开放封闭原则 (对于拓展是开放的, 对于修改是封闭的)
  2. 依赖倒转原则 (程序都依赖抽象,而不是相互依赖)

第二版代码:
抽象观察者类(同事类):

package observer2;
public abstract  class observer {
    protected String name ;
    protected secretary s;

    public observer(String name, secretary s) {
        this.name = name;
        this.s = s;
    }
    public abstract void update();
}

具体观察者1(看股票的同事)

package observer2;
public class stockObserver extends  observer {
    public stockObserver(String name, secretary s) {
        super(name, s);
    }
    @Override
    public void update() {
        String format = String.format("%s,%s关闭股票行情,继续工作",s.getAction(),name);
        System.out.println(format);
    }
}

具体观察者2(看NBA的同事)

package observer2;

public class NBAObserver extends observer{
    public NBAObserver(String name, secretary s) {
        super(name, s);
    }

    @Override
    public void update() {
        String format = String.format("%s,%s关闭股票行情,继续工作",s.getAction(),name);
        System.out.println(format);
    }
}

前台秘书类(把所有与具体观察者耦合的地方都改为“抽象观察者”)

package observer2;
import java.util.*;

public class secretary {
    private List<observer> observers = new ArrayList<observer>();
    private String action;

    public String getAction() {
        return action;
    }

    public void setAction(String action) {
        this.action = action;
    }

    public void attach(observer o) {
        observers.add(o);
    }

    public void detach(observer o) {
        observers.remove(o);
    }

    public void Notify() {
        for (observer o : observers) {
            o.update();
        }
    }
}

客户端:

package observer2;
public class client {
    public static void main(String[] args) {
        secretary s = new secretary();
        stockObserver tongshi1 = new stockObserver("zyy",s);
        NBAObserver tongshi2 = new NBAObserver("yan",s);
        s.attach(tongshi1);
        s.attach(tongshi2);
        s.setAction("老板回来了");
        s.Notify();
        s.detach(tongshi1);
        s.setAction("老板又来了");
        s.Notify();
    }
}

在这里插入图片描述
但是,这里前台秘书类是一个具体的类,也应该抽象出来,假如前台不在,老板就成了通知者

第三版代码:
通知者接口:

package observer3;

public interface subject {
    void attach(observer o);
    void detach(observer o);
    void Notify();
    String getAction();
}

具体通知者(老板)

package observer3;

import java.util.*;
public class boss implements subject {
    private List<observer> observers = new ArrayList<>();
    private String action;

    @Override
    public void attach(observer o) {
        observers.add(o);
    }

    @Override
    public void detach(observer o) {
        observers.remove(o);
    }

    @Override
    public void Notify() {
        for (observer o : observers) {
            o.update();
        }
    }

    public String getAction() {
        return action;
    }

    public void setAction(String action) {
        this.action = action;
    }
}

前台秘书类代码与老板类类似
对于观察者,需要改的地方就是把与前台耦合的地方都改为抽象通知者
抽象观察者:

package observer3;

public abstract class observer {
    protected String name;
    protected subject sub;

    public observer(String name, subject sub) {
        this.name = name;
        this.sub = sub;
    }
    public abstract void update();
}

具体观察者(看股票的同事):

package observer3;

public class stockObserver extends  observer {
    public stockObserver(String name, subject sub) {
        super(name, sub);
    }

    @Override
    public void update() {
        String format = String.format("%s,%s 关闭股票行情,继续工作",sub.getAction(),name);
        System.out.println(format);
    }
}

客户端:

package observer3;

public class client {
    public static void main(String[] args) {
        boss b = new boss();
        stockObserver tongshi1 = new stockObserver("zyy",b);
        stockObserver tongshi2 = new stockObserver("yan",b);
        b.attach(tongshi1);
        b.attach(tongshi2);
        b.detach(tongshi1);
        b.setAction("我回来了");
        b.Notify();
    }
}

在这里插入图片描述
上述代码的结构图为:
在这里插入图片描述
观察者模式:又叫发布——订阅模式
定义了一种一对多的依赖关系,让多个观察者(上述例子中的同事)同时监听某一个主题对象(上述例子中的前台秘书)。这个主题对象在状态发生变化时,会通知所有观察者对象。
在这里插入图片描述
Subject:主题或者抽象通知类,一般用一个抽象类或者一个接口实现。它将所有对观察者的引用保存在一个聚集中,每个通知类都可以有任意数量的观察者,可以增加和删除观察者对象。

再来看一个场景:
警察围捕嫌疑犯
观察者:便衣警察
通知类:嫌疑犯
(多个便衣警察观察嫌疑犯状态的变化)
具体代码:
观察者接口:

package observer_police;

public interface Observer {
    void update(String message,String name);
}

具体观察者:

package observer_police;

public class Bianyi1 implements Observer {
    private String bname = "bianyi1";
    @Override
    public void update(String message, String name) {
        System.out.println(bname+":"+name+"那里有情况"+message);
    }
}

其余具体观察者与之类似

通知者类接口:

package observer_police;

public interface xianyifan {
    void addObserver(Observer observer);
    void removeObserver(Observer observer);
    void notice(String message);
}

具体通知者:

package observer_police;

import java.util.ArrayList;
import java.util.List;

public class xianyifan1 implements xianyifan {
    private String name = "大熊";
    private List<Observer> observerList = new ArrayList<Observer>();
    @Override
    public void addObserver(Observer observer) {
        if(!observerList.contains(observer)){
            observerList.add(observer);
        }
    }

    @Override
    public void removeObserver(Observer observer) {
        if(observerList.contains(observer)){
            observerList.remove(observer);
        }
    }

    @Override
    public void notice(String message) {
        for(Observer observer:observerList){
            observer.update(message,name);
        }
    }
}

其余通知者类与之类似
客户端:

package observer_police;

public class client {
    public static void main(String[] args) {
        xianyifan xyf1 = new xianyifan1();
        xianyifan xyf2= new xianyifan2();
        Observer o1 = new Bianyi1();
        Observer o2 = new Bianyi2();
        Observer o3 = new Bianyi3();
        xyf1.addObserver(o1);
        xyf1.addObserver(o2);
        xyf1.addObserver(o3);

        xyf2.addObserver(o2);
        String message1 = "要逃跑";
        String message2 = "已抓捕";
        xyf1.notice(message1);
        xyf2.notice(message2);
    }
}

在这里插入图片描述
观察者模式的特点:
将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是需要维护相关对象间的一致性,我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、拓展和重用都带来不便。
观察者模式的关键对象是主题(通知者)和观察者,主题(通知者)可以有任意数目的依赖它的观察者,一旦主题的状态发生变化,所有依赖它的观察者都可以得到通知。主题发出通知时,并不知道谁是它的观察者,也就是说,具体观察者是谁,根本不需要知道。
何时用观察者模式?
当一个对象的改变需要同时改变其他对象,并且它不知道有多少对象需要改变。
观察者模式所做的工作就是在解除耦合,让耦合的双方都依赖于抽象,而不是依赖于具体,从而使得各自的变化都不会影响另外一边的变化。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值