设计模式——观察者模式详解

前言

观察者模式是使用频率最高的设计模式之一,当对象间存在一对多关系时候就可以使用观察者模式。
观察者模式又被称为

  • 发布-订阅模式
  • 模型-视图模式
  • 源-监听器模式
  • 从属者模式

观察者模式是一种对象行为型模式。定义对象间的一种一对多依赖关系,一个对象发生更改时候,自动通知其他对象,被通知的对象称为观察者。
例如:
一个变量的修改,需要自动通知依赖它的对象。

观察者模式结构

观察者模式结构图中主要有以下角色

  1. Subject(目标):指被观察的对象,其中定义了一个观察者集合,一个目标可以接受任意数量的观察者观察,提供一系列方法增加和删除观察者对象,同时还定义了通知方法。可以为接口、抽象类和具体类。
  2. ConcreteSubject(具体目标):目标类的子类,通常包含经常发生改变的数据,当其状态改变,向它的各个观察者发出通知,同时如何目标类中有抽象业务逻辑方法,其也会实现。如果无需扩展,则具体目标类可以省略。
  3. Observe(观察者):观察者对观察目标的改变做出反应,一般定义为接口,声明更新数据的方法update(),又被称为抽象观察者。
  4. ConcreteObserver(具体观察者):其维护一个指向具体目标对象的引用,存储具体观察者的有关状态,其状态需要和具体目标的状态保持一致,实现**update()**方法。
    在这里插入图片描述

Java对于观察者模式的支持

在JDK的java.util包中,提供了Observable类以及Observer接口。其是从jdk1.0便开始提供的类与接口,但是在jdk9之后弃用,其api中解释如下。
在这里插入图片描述
所以此处不多解释。

观察者模式与MVC

MVC架构包括三个角色:

  1. 模型(Model)
  2. 视图(View)
  3. 控制器(Controller)
    其中模型可以对应观察者模式中的观察目标,视图对应观察者,而控制器充当二者中间的中介者,模型层的数据发生改变时,视图层自动改变其显示内容。

总结

观察者模式的主要优点:

  1. 可以实现表示层和数据逻辑层的分离,定义稳定的消息更新传递机制,抽象更新接口,可以让各种各样不同的表示层充当具体观察者。
  2. 在观察目标和观察者之间建立了一个抽象的耦合,观察对象和观察者解耦合。
  3. 简化一对多系统设计的难度。
  4. 观察者模式满足“开闭原则”。

观察者模式的主要缺点:

  1. 如果一个观察目标对象有很多观察者,那么通知每一个观察者时间会很长。
  2. 若观察者与观察目标之间存在循环依赖,可能会触发循环调用,可能导致系统崩溃。
  3. 观察者模式只会让观察者知道目标发生了变化,而不知道发生了什么变化。

例子

在这里插入图片描述
在拿到一个新的需求的时候,我们先分析一下用什么设计模式,为什么要用这个设计模式。

我们可以看到这个需求中,可以抽象出以下几个角色。

  • 股票购买者
  • 股票

而事件是当变化幅度达到5%时候,通知所有购买了股票的股民。
显而易见,这就是一个典型的观察者模式的引用。

//客户端类
public class Client {
    public static void main(String[] args) {
        Subject subject1=new ConcreteSubject("股票1",100.0);
        Subject subject2=new ConcreteSubject("股票2",100.0);
        Subject subject3=new ConcreteSubject("股票3",100.0);

        Observer obs1=new ConcreteObserver("股民1");
        Observer obs2=new ConcreteObserver("股民2");
        Observer obs3=new ConcreteObserver("股民3");

        subject1.attachUser(obs1);
        subject1.attachUser(obs3);

        subject2.attachUser(obs1);
        subject2.attachUser(obs2);

        subject3.attachUser(obs2);
        subject3.attachUser(obs3);

        subject1.setValue(200.0);

        subject2.setValue(300.0);

    }
}
public interface Subject {
    public String getName();
    public void setName(String name);
    public Double getValue();
    public void setValue(Double val);
    public void attachUser(Observer obs);
    public void deleteUser(Observer obs);
}

public class ConcreteSubject implements Subject{
    private String name;
    private Double value;
    private ArrayList<Observer> users;

    @Override
    public void attachUser(Observer obs){
        this.users.add(obs);
    }

    @Override
    public void deleteUser(Observer obs){
        this.users.remove(obs);
    }

    public ConcreteSubject(String name,Double val){
        this.name=name;
        this.value=val;
        users=new ArrayList<>();
    }

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public void setName(String name) {
        this.name=name;
    }

    @Override
    public Double getValue() {
        return this.value;
    }

    @Override
    public void setValue(Double val) {
        Double change=(val-this.value)/this.value;
        if(change>=0.05){
            for(Observer user:users){
                user.notify(this,val,change);
            }
        }
        this.value=val;
    }
}

public interface Observer {
     public void notify(Subject shares,Double aftval,Double change);
}
public class ConcreteObserver implements Observer{

    private String userName;

    public ConcreteObserver(String name){
        this.userName=name;
    }

    @Override
    public void notify(Subject shares, Double aftval, Double change) {
        System.out.println(userName+"的股票:"+shares.getName()+"\t"+"原价为:"+shares.getValue()+";"+"现价为:"+aftval+";"+"涨幅为:"+change*100+"%");
    }
}

在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值