• Java设计模式----观察者模式详解


    【声明】

    欢迎转载,但请保留文章原始出处→_→

    生命壹号:http://www.cnblogs.com/smyhvae/

    文章来源:http://www.cnblogs.com/smyhvae/p/3899208.html

     

    【正文】

    一、观察者模式的定义:

    简单地说,观察者模式定义了一个一对多的依赖关系,让一个或多个观察者对象监听一个主题对象。这样一来,当被观察者状态发生改变时,需要通知相应的观察者,使这些观察者对象能够自动更新。例如:GUI中的事件处理机制采用的就是观察者模式。

    二、观察者模式的实现:

    • Subject(被观察的对象接口):规定ConcreteSubject的统一接口 ; 每个Subject可以有多个Observer;
    • ConcreteSubject(具体被观察对象):维护对所有具体观察者的引用的列表 ;–状态发生变化时会发送通知给所有注册的观察者。
    • Observer(观察者接口):规定ConcreteObserver的统一接口;定义了一个update()方法,在被观察对象状态改变时会被调用。
    • ConcreteObserver(具体观察者):维护一个对ConcreteSubject的引用;特定状态与ConcreteSubject同步; 实现Observer接口,update()方法的作用:一旦检测到Subject有变动,就更新信息。

    图表描述如下:

    注:在被观察者类中需要有一个集合维护所有观察者。

    三、举例说明:

    【方案一】:自己定义接口或者类来实现观察者模式。

    步骤如下:

    (1)定义被观察者所具有的接口:

     1 package com.vince.observer;
     2 public interface Observable {
     3     //注册为一个观察者    
     4     public void registerObserver(Observer observer);
     5     
     6     //取消观察者    
     7     public void removeObserver(Observer observer);
     8     
     9     //通知所有观察者更新信息    
    10     public void notifyObservers();
    11 }

    (2)定义具体的被观察者:杯子

     1 package com.vince.observer;
     2 import java.util.Vector;
     3 
     4 public class Cup implements Observable{
     5     //被观察者维护的一个观察者对象列表
     6     private Vector<Observer> vector = new Vector<Observer>();
     7     private float price;
     8     
     9     public Cup(float price){
    10         this.price = price;
    11     }
    12     
    13     public float getPrice() {
    14         return price;
    15     }
    16     public void setPrice(float price) {
    17         //修改价格时,通知所有观察者
    18         this.price = price;
    19         notifyObservers();
    20     }
    21     @Override
    22     public void registerObserver(Observer observer) {
    23         //注册观察者
    24         vector.add(observer);
    25     }
    26     @Override
    27     public void removeObserver(Observer observer) {
    28         //取消观察者
    29         vector.remove(observer);
    30     }
    31     @Override
    32     public void notifyObservers() {
    33         //实现通知所有的观察者对象
    34         for (Observer observer:vector) {
    35             observer.update(price);
    36         }
    37     }
    38 }

    (3)定义观察者所具有的共同的接口:(更新数据最终当然是在观察者那里进行啦)

    1 package com.vince.observer;
    2 
    3 public interface Observer {
    4     public void update(float price);
    5 }

    (4)定义具体的观察者对象:

     1 package com.vince.observer;
     2 public class Person implements Observer{
     3     private String name;
     4     public Person(String name){
     5         this.name = name;
     6     }
     7     @Override
     8     public void update(float price) {
     9         System.out.println(name+"关注的杯子的价格已更新为:"+price);
    10     }
    11 }

    (5)测试:

     1 package com.vince.observer;
     2 public class Test {
     3     public static void main(String[] args) {
     4         //创建一个被观察者对象
     5         Cup doll  = new Cup(3000);
     6         //创建两个观察者对象
     7         Person p1 = new Person("生命壹号");
     8         Person p2 = new Person("生命贰号");
     9         //注册成为一个观察者
    10         doll.registerObserver(p1);
    11         doll.registerObserver(p2);
    12         
    13         System.out.println("第一轮促销:");
    14         doll.setPrice(2698);// 价格变动
    15         System.out.println("第二轮促销:");
    16         doll.setPrice(2299);//
    17         System.out.println("第三轮促销:");
    18         doll.setPrice(1998);
    19         
    20         doll.removeObserver(p2);    //将生命二号移除
    21         System.out.println("第四轮促销:");
    22         doll.setPrice(1098);        
    23         
    24     }
    25 }

    运行后,显示结果如下:

    【方案二】:直接调用JDK的API去实现。

    步骤如下:

    (1) 通过继承Observable类实现具体的被观察者对象:

     1 package com.vince.observer2;
     2 import java.util.Observable;
     3 
     4 public class Cup extends Observable{
     5     private float price;
     6     
     7     public Cup(float price){
     8         this.price = price;
     9     }
    10     public float getPrice() {
    11         return price;
    12     }
    13     public void setPrice(float price) {
    14         this.price = price;
    15         this.setChanged();//通知,数据已改变
    16         this.notifyObservers();
    17     }
    18     
    19     
    20 }

    (2)通过实现java.util.Observer接口实现具体的观察者对象:

     1 package com.vince.observer2;
     2 import java.util.Observable;
     3 import java.util.Observer;
     4 
     5 public class Person implements Observer{
     6     private String name;
     7     public Person(String name){
     8         this.name = name;
     9     }
    10     @Override
    11     public void update(Observable o, Object arg) {
    12         if(o instanceof Cup){
    13             Cup cup = (Cup)o;
    14             System.out.println(name+"关注的杯子价格已更新为:"+cup.getPrice());
    15         }
    16     }
    17 }

    (3)测试:

     1 package com.vince.observer2;
     2 public class Test {
     3     public static void main(String[] args) {
     4         Cup cup = new Cup(3000);
     5         Person p1 = new Person("生命壹号");
     6         Person p2 = new Person("生命贰号");
     7         cup.addObserver(p1);
     8         cup.addObserver(p2);
     9         System.out.println("第一轮促销");
    10         cup.setPrice(2988);
    11         System.out.println("第二轮促销");
    12         cup.setPrice(2698);
    13         
    14         cup.deleteObserver(p2);
    15         System.out.println("第三轮促销");
    16         cup.setPrice(1998);
    17     }
    18 }

    运行后,结果如下:

    【工程文件】

    链接:http://pan.baidu.com/s/1c03rLFM

    密码:hois

    四、总结:(观察者模式的作用)

    • 观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者列表。

            由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。如果被观察者和观察者都被扔到一起,那么这个对象必然跨越抽象化和具体化层次。

    • 观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知。

    推荐学习链接:http://blog.csdn.net/crave_shy/article/details/21235855

    我的公众号

    想学习代码之外的软技能?不妨关注我的微信公众号:生命团队(id:vitateam)。

    扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外:

  • 相关阅读:
    mysql数据创建带参的存储过程,并在存储过程中调用另一个存储过程
    python解析.xls/.xlsx文件--openpyxl模块(第三方)
    python使用django开发接口
    Mysql创建存储过程--批量插入数据
    Centos7下安装kafka,并使用python操作kafka的简单使用
    Centos7下安装JDK1.8
    Centos7下docker的安装
    python解析.xml文件-- xmltodict模块(第三方)
    解决:git SSL certificate problem: unable to get local issuer certificate
    AD域是什么意思?
  • 原文地址:https://www.cnblogs.com/qianguyihao/p/3899208.html
Copyright © 2020-2023  润新知