资讯专栏INFORMATION COLUMN

观察者模式

Miracle / 3180人阅读

摘要:简介学习本篇博文,我们知道在什么场景下使用观察者模式。观察者模式给我们在今后开发中什么思想。为什么需要观察者模式从定义中我们可以知道观察者模式当对象改变时,其他依赖的对象都会收到改变信息的状态。

简介

1.学习本篇博文,我们知道在什么场景下使用观察者模式。
2.观察者模式的优缺点。
3.观察者模式给我们在今后开发中什么思想。

场景

某家科技公司目前在开发一个项目,设计小组需要上报项目的进度给部门经理,主要有两个模块更新原有的业务模块进度和添加新业务的模块完成进度。
那么部门经理需要什么途径能最快的得到进度的信息呢?或者可能是项目总监也想参与,去获取到最新的进展情况呢?我们改如何去考虑这个业务呢?

很多时候我们就会想到继承去解决这一情况,毕竟OO编写思想时刻影响这一我们,但是如果某天项目经理出差了,他不想看项目进度了,那我们又改怎么办呢?

我们能不能就是设计一个业务,让能想知道该进度的人,不管什么时候,只要有开发者上报进度的时候就一下他就得到进度的信息,而他无需去关系这个过程。

你是否能想到合适的解决方案呢?

答案就在下文中,你准备好了吗?

问题 什么是观察者模式?

观察者模式定义一系列对象之间的一对多关系,当一个对象改变、更新状态时,依赖它的都会收到通知改变或者更新。

为什么需要观察者模式?

从定义中我们可以知道观察者模式当对象改变时,其他依赖的对象都会收到改变信息的状态。

从本例分析项目经理想知道进度情况,他只需要绑定进度,他就可以知道进度信息了,而无需关心如何操作,如果再增加一个想知道进度信息老板呢?也很容易,也让老板绑定进度信息数据就好了,不想知道的时候就解除绑定,就不在获取进度信息了。

所以在本案例场景中,观察者是我们这个场景非常合适的设计。

如何实现观察者模式? 自定义观察者模式 实现如下
我们先来看一下这个UML类图进行分析

具体实现步骤

1.构造一个主题Subject或者是一个被观察者Observeable,这是一个接口或者是抽象类

  public interface Subject {
   //注册观察者
   void registerObserver(Observer observe);
   //解除绑定观察者
   void unRegisterObserver(Observer observe);
   //更新数据
   void notifyObservers();
 }

2.构建一个被观察者实现该主题接口如本例的 DevelopmentProgressData.class,这里是进度信息数据
在registerObserver(Observer o);//方法中将观察者添加到注册列表中
在unRegisterObserve(Observer o);//删除观察者

public class DevelopmentProgressData implements Subject {
 @Override
   public void registerObserver(Observer observer) {
       //将观察者添加到列表中
       arrayObserve.add(observer);
   }

   @Override
   public void unRegisterObserver(Observer observer) {
       int i = arrayObserve.indexOf(observer);
       if (i >= 0) {
           //将观察者从列表中解除
           arrayObserve.remove(i);
       }

   }
   //通知所以观察者数据更新了
   @Override
   public void notifyObservers() {

       for (int i = 0; i < arrayObserve.size(); i++) {
           Observer o = (Observer) arrayObserve.get(i);
           o.update(completeProgress, updateProgress);
       }
   }
}

3.构建一个观察者接口Observer

 public interface Observer {
    //更新数据
    void update(int completeProgress, int updateProgress);
 }

4.可构建一个展示数据的接口(可忽略)
有展示数据的方法,观察者要实现这个方法 查看本例的 DisplaySchedule

public interface DisplaySchedule {
   void display();
}

5.定义观察者(模拟该类就是产品经理观察者),需实现接口Observes、DisplaySchedule(可忽略),
<1>、将主题Subject设置为观察者的属性,并将其作为观察者的构造函数如 ProductManagerObserver.class
调用 developmentProgressSubject.registerObserver(this);将观察者注册到观察列表中

public class ProductManagerObserver implements Observer, DisplaySchedule {

    private int completeProgress;//完成进度
    private int updateProgress;//更新进度
    //将主题当成观察者的属性
    private Subject developmentProgressSubject;

    public ProductManagerObserver(Subject developmentProgressSubject) {
        this.developmentProgressSubject = developmentProgressSubject;
        //注册该观察者
        developmentProgressSubject.registerObserver(this);
    }

    @Override
    public void display() {
        System.out.println("产品经理管理者显示当前数据 完成进度为: " + completeProgress + "更新修改进度为:" + updateProgress);
    }

    @Override
    public void update(int completeProgress, int updateProgress) {
        this.completeProgress = completeProgress;
        this.updateProgress = updateProgress;
        display();
    }
}
测试

RunTest.class

public class RunTest {

    public static void main(String[] args) {

        DevelopmentProgressData developmentProgressData = new DevelopmentProgressData();
        ProductManagerObserver productManagerObserver = new ProductManagerObserver(developmentProgressData);
        ProjectManagerObserver projectManagerObserver = new ProjectManagerObserver(developmentProgressData);
        developmentProgressData.setCurrentData(34, 45);
        //当项目经理出差了,不观察项目进度了就取消订阅了
        developmentProgressData.unRegisterObserver(projectManagerObserver);
        //当前只有产品经理获取到数据
        developmentProgressData.setCurrentData(46, 90);
    }
}
输出结果
C:Javajdk1.8.0_161in...
产品经理管理者显示当前数据 完成进度为: 34更新修改进度为:45
项目管理真显示当前数据完成进度为: 34更新修改进度为:45
产品经理管理者显示当前数据 完成进度为: 46更新修改进度为:90

Process finished with exit code 0
根据java.util.observerable包下的Observerable.class实现观察者模式功能 实现如下
具体实现步骤

1.首先观察者需要实现java.util.Observer,然后将其被观察者=>java.util.Observaerable作为其观察者的构造函数

<1>、通过observeable.addObserver(this)添加观察者

public class BossMngObserver implements Observer, DisplayIllustrate {

 private Observable observable;
 private int valuableProductNum; //库存有贵重产品
 private int normalProductNum;   //普通产品

 public BossMngObserver(Observable observable) {
     this.observable = observable;
     observable.addObserver(this);
 }

 @Override
 public void disPlay() {
     System.out.println("总经理观察数据改变:贵重产品数量: " + valuableProductNum + "普通产品数量: " + normalProductNum);
 }
//<2>、实现 Observer更新数据方法
//看本例的包下的observe的三个类
 @Override
 public void update(Observable o, Object arg) {
     if (o instanceof InventoryData) {
         InventoryData inventoryData = (InventoryData) o;
         this.valuableProductNum = inventoryData.getValuableProductNum();
         this.normalProductNum = inventoryData.getNormalProductNum();
         disPlay();
     }
 }
  }

2.被观察者需要继承java.util.Observerable,

<1>、然后先调用setChanged()方法

<2>、在进行调用notifyObserves()更新数据

  public class InventoryData extends Observable {

    private int valuableProductNum; //库存有贵重产品
    private int normalProductNum;   //普通产品

    public void setCurrentData(int valuableProductNum, int normalProductNum) {
        this.valuableProductNum = valuableProductNum;
        this.normalProductNum = normalProductNum;
        statusChange();
    }

    private void statusChange() {
    //先调用 setChanged();
        setChanged();
        notifyObservers();
    }
 }
测试

3.Test.class

public class Test {
    public static void main(String[] args) {

        InventoryData inventoryData = new InventoryData();

        ValuableInfoMngObserver io = new ValuableInfoMngObserver(inventoryData);

        //io.deleteObserve();
        inventoryData.setCurrentData(20, 30);

        NormalInfoMngObserver no = new NormalInfoMngObserver(inventoryData);

        //no.deleteObserver();
        inventoryData.setCurrentData(15, 27);

        BossMngObserver bossMngObserver = new BossMngObserver(inventoryData);

        inventoryData.setCurrentData(10, 50);
    }
}
下载

观察者模式案例代码

总结

观察者模式的让我们知道了在设计开发的时候一定要“多用组合,少用继承”。

我们设计开发是应该是针对接口变成,而不针对实现编程。

在java.util.*下的Observer和Observable可以实现观察者,但是Observable是一个类,这样我们是不违背了“多用组合少用继承”的OO编程思想,是的没错在java.util.Observable类违背了该规则。

我的GitHub博客 设计模式

大家可以进入这里学习设计模式

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/76995.html

相关文章

  • 设计模式察者设计模式

    摘要:关键概念理解观察者设计模式中主要区分两个概念观察者指观察者对象,也就是消息的订阅者被观察者指要观察的目标对象,也就是消息的发布者。 原文首发于微信公众号:jzman-blog,欢迎关注交流! 最近补一下设计模式相关的知识,关于观察者设计模式主要从以下几个方面来学习,具体如下: 什么是观察者设计模式 关键概念理解 通知观察者的方式 观察者模式的实现 观察者模式的优缺点 使用场景 下面...

    NotFound 评论0 收藏0
  • 设计模式察者模式与发布订阅模式

    摘要:观察者模式与发布订阅的区别在模式中,知道,同时还保留了的记录。发布者订阅者在大多情况下是异步方式使用消息队列。图片源于网络侵权必删如果以结构来分辨模式,发布订阅模式相比观察者模式多了一个中间件订阅器,所以发布订阅模式是不同于观察者模式的。 学习了一段时间设计模式,当学到观察者模式和发布订阅模式的时候遇到了很大的问题,这两个模式有点类似,有点傻傻分不清楚,博客起因如此,开始对观察者和发布...

    BaronZhang 评论0 收藏0
  • 设计模式 -- 察者模式

    摘要:总结一下从表面上看观察者模式里,只有两个角色观察者被观察者而发布订阅模式,却不仅仅只有发布者和订阅者两个角色,还有第三个角色经纪人存在。参考链接观察者模式发布订阅模式 做了这么长时间的 菜鸟程序员 ,我好像还没有写过一篇关于设计模式的博客...咳咳...意外,纯属意外。所以,我决定,从这一刻起,我要把设计模式在从头学习一遍,不然都对不起我这 菜鸟 的身份。那这次,就从观察者模式开始好啦...

    chengtao1633 评论0 收藏0
  • 设计模式 -- 察者模式

    摘要:总结一下从表面上看观察者模式里,只有两个角色观察者被观察者而发布订阅模式,却不仅仅只有发布者和订阅者两个角色,还有第三个角色经纪人存在。参考链接观察者模式发布订阅模式 做了这么长时间的 菜鸟程序员 ,我好像还没有写过一篇关于设计模式的博客...咳咳...意外,纯属意外。所以,我决定,从这一刻起,我要把设计模式在从头学习一遍,不然都对不起我这 菜鸟 的身份。那这次,就从观察者模式开始好啦...

    makeFoxPlay 评论0 收藏0
  • 订阅发布模式察者模式的区别

    摘要:或许以前认为订阅发布模式是观察者模式的一种别称,但是发展至今,概念已经有了不少区别。参考文章订阅发布模式和观察者模式真的不一样 首选我们需要先了解两者的定义和实现的方式,才能更好的区分两者的不同点。 或许以前认为订阅发布模式是观察者模式的一种别称,但是发展至今,概念已经有了不少区别。 订阅发布模式 在软件架构中,发布-订阅是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特...

    ysl_unh 评论0 收藏0
  • 我的Java设计模式-察者模式

    摘要:为了帮助灰太狼摆脱被老婆平底锅抽的悲剧,发起了解救灰太狼的行动,必须要知道观察者模式。持有观察者对象的集合。设计模式源码下载 相信大家都有看过《喜洋洋与灰太狼》,说的是灰太狼和羊族的斗争,而每次的结果都是灰太狼一飞冲天,伴随着一句我还会回来的......。为灰太狼感到悲哀,抓不到羊,在家也被老婆平底锅虐待。灰太狼为什么会这么背? 很简单,灰太狼本身就有暴露行踪的属性,羊咩咩就能知晓灰太...

    smartlion 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<