《观察者模式》

目录

1.常用场景

2.观察者模式原理

3.观察者模式实现

        (1)抽象主题

(2)观察者

(3)测试类

4.JDK中的观察者

(1)抽象观察者

(2)被观察类

5.优缺点

(1)优点

(2)缺点


1.常用场景

  •         当一个对象状态的改变需要改变其他对象时。比如,商品库存数量发生变化时,需要通知商品详情页、购物车等系统改变数量。
  •         一个对象发生改变时只想要发送通知,而不需要知道接收者是谁。比如,订阅微信公众号的文章,发送者通过公众号发送,订阅者并不知道哪些用户订阅了公众号。
  •         需要创建一种链式触发机制时。比如,在系统中创建一个触发链,A 对象的行为将影响 B 对象,B 对象的行为将影响 C 对象……这样通过观察者模式能够很好地实现。
  •         微博或微信朋友圈发送的场景。这是观察者模式的典型应用场景,一个人发微博或朋友圈,只要是关联的朋友都会收到通知;一旦取消关注,此人以后将不会收到相关通知。
  •         需要建立基于事件触发的场景。比如,基于 Java UI 的编程,所有键盘和鼠标事件都由它的侦听器对象和指定函数处理。当用户单击鼠标时,订阅鼠标单击事件的函数将被调用,并将所有上下文数据作为方法参数传递给它。

2.观察者模式原理

  • Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
  • ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
  • Observer:抽象观察者,是观察者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
  • ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。在具体观察者中维护一个指向具体目标对象的引用,它存储具体观察者的有关状态,这些状态需要与具体目标保持一致.

3.观察者模式实现

        (1)抽象主题

public abstract class Subject {
    List<Observer> observers;
    Subject(){
        observers = new ArrayList<Observer>();
    }
    // 添加观察者
    public void addObserver(Observer observer){
        observers.add(observer);
    }
    // 删除观察者
    public void removeObserver(Observer observer){
        observers.remove(observer);
    }
    // 通知观察者
    public abstract void notifyObservers(Message message);
}

public class WorkSubject extends Subject {
    @Override
    public void notifyObservers(Message message) {
        // 工作状态发生改变,通知所有观察者
        for (Observer observer : observers) {
            observer.process(message);
        }
    }
}

        (2)观察者

public interface Observer {
    void process(Message message);
}

public class PCObserver implements Observer {
    private  String name;
    PCObserver(){
        super();
        name = "电脑端";
    }
    @Override
    public void process(Message message) {
        System.out.println("【"+name+"】收到消息:"+message.getMessage());
    }
}

public class MobileObserver implements Observer {
    private  String name;
    MobileObserver(){
        super();
        name = "手机端";
    }
    @Override
    public void process(Message message) {
        System.out.println("【"+name+"】收到消息:"+message.getMessage());
    }
}

        (3)测试类

public class Test {
    public static void main(String[] args) {
        Subject subject = new WorkSubject();
        Observer pcObserver = new PCObserver();
        Observer mobileObserver = new MobileObserver();
        Message message = new Message("用户下线。。。。");
        //添加观察者
        subject.addObserver(pcObserver);
        subject.addObserver(mobileObserver);
        //通知观察者
        subject.notifyObservers(message);
    }
}

4.JDK中的观察者

(1)抽象观察者

  • java.util.Observer 接口: 该接口中声明了一个方法,它充当抽象观察者

(2)被观察类

  • java.util.Observable 类: 充当观察目标类(被观察类) , 在该类中定义了一个Vector集合来存储观察者对象.
  • void addObserver(Observer o) 方法:用于将新的观察者对象添加到集合中。
  • void notifyObservers(Object arg) 方法:调用集合中的所有观察者对象的 update方法,通知它们数据发生改变。通常越晚加入集合的观察者越先得到通知。
  • void setChange() 方法:用来设置一个 boolean 类型的内部标志,注明目标对象发生了变化。当它为true时,notifyObservers() 才会通知观察者。

(3)代码改造


public class WorkSubject extends Observable {
    public void onMessage(Message message){
        // 设置消息状态
        setChanged();
        // 通知所有观察者
        notifyObservers(message);
    }
}
//具体观察者
public class MobileObserver implements Observer {
    private  String name;
    MobileObserver(){
        super();
        name = "手机端";
    }

    @Override
    public void update(Observable o, Object arg) {
        if (arg instanceof Message){
            System.out.println(name+" 收到消息:"+((Message) arg).getMessage());
        }
    }
}
public class PCObserver implements Observer {
    private  String name;
    PCObserver(){
        super();
        name = "电脑端";
    }
    @Override
    public void update(Observable o, Object arg) {
        if (arg instanceof Message){
            System.out.println(name+" 收到消息:"+((Message) arg).getMessage());
        }
    }
}
//消息
public class Message {
    private  String message;
    Message(String message){
        this.message=message;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}
//测试类
public class Test {
    public static void main(String[] args) {
        WorkSubject subject = new WorkSubject();
        Observer pcObserver = new PCObserver();
        Observer mobileObserver = new MobileObserver();
        Message message = new Message("用户下线。。。。");
        //添加观察者
        subject.addObserver(pcObserver);
        subject.addObserver(mobileObserver);
        //通知观察者
        subject.onMessage(message);
    }
}

5.优缺点

(1)优点

  • 松耦合和高扩展性:观察者和被观察者之间的耦合是抽象的,这允许系统更容易地扩展和修改。增加新的观察者或修改被观察者的行为时,不需要修改已有的代码。
  • 自动触发机制:当被观察对象的状态发生变化时,系统可以自动通知所有注册的观察者,这简化了事件处理和状态更新的过程。
  • 符合开闭原则:这一设计原则要求软件实体对扩展开放,对修改关闭。观察者模式支持这一原则,因为可以在不修改现有代码的情况下添加新的功能。

(2)缺点

  • 性能问题:当存在大量的观察者时,通知所有这些观察者可能会成为性能瓶颈,特别是当每个观察者都需要花费较多时间处理通知时
  • 循环依赖问题:如果观察者和被观察者之间存在循环依赖,这可能导致在通知过程中出现循环调用,从而引发系统崩溃或不稳定。
  • 缺乏对变化细节的了解:观察者模式主要通知观察者目标对象的状态已经改变,但不提供关于如何或为什么会发生这种变化的信息。     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值