zoukankan      html  css  js  c++  java
  • 设计模式--观察者模式

    设计模式--观察者模式

    1、观察者模式

    观察者模式:定义对象间一种一对多的依赖关系,当一个对象状态发生变化时,所有依赖于它的对象都得到通知,并被自动更新。

    2、观察者模式的结构

    • 角色

      • 主题(Subject):主题是一个接口,该接口规定了具体主题需要实现的方法,比如添加,删除观察者以及通知观察者的方法。

      • 观察者(ObServer): 观察者是一个接口,该接口规定了具体观察者用来获得数据的方法。

      • 具体主题(ConcreteSubject):具体主题是实现主题接口的类的一个实例,该实例包含观察者关心的数据,而且这些数据可能经常发生变化。具体主题需要使用一个集合来存放观察者的引用,以便数据变化时通知具体的观察者。

      • 具体观察者(ConreteObserver):具体观察者是实现观察者接口的类的一个实例。具体观察者包含具体主题的引用,以便让具体主题将自己添加到具体主题的集合中,使自己成为具体主题的观察者,或者从具体主题的集合中将自己删除,不成为具体主题的观察者。

    • UML图

      

    3、观察者模式举例

     主题接口:Subject.java

     1 package com.nick.pattern.observer;
     2 
     3 import java.util.ArrayList;
     4 
     5 /**
     6  * @ 主题接口:定义了观察者数组(存放观察者的信息)和抽象方法
     7  * @author nick
     8  *
     9  */
    10 public interface Subject {  
    11    ArrayList<Observer> observers =null;
    12   void attach(Observer obs);
    13 void detach(Observer obs);
    14 void cry();  //相当于notify()通知方法
    15 }

     观察者接口:Observer.java

    1 package com.nick.pattern.observer;
    2 /**
    3  * @ 观察者接口
    4  * @author nick
    5  */
    6 public interface Observer {
    7     void response(); //相当于update()方法 
    8 }

     具体主题类:Cat.java

     1 package com.nick.pattern.observer;
     2 
     3 import java.util.ArrayList;
     4 
     5 /**
     6  * @ 具体主题:猫(老鼠和狗是观察者,他们通过观察猫的行为,做出反应)
     7  * @author nick
     8  *
     9  */
    10 public class Cat implements Subject {
    11     ArrayList<Observer> observers = new ArrayList<Observer>();
    12     
    13     @Override
    14     public void attach(Observer obs) {
    15         observers.add(obs);
    16     }
    17 
    18     @Override
    19     public void detach(Observer obs) {
    20         observers.remove(obs);    
    21     }
    22 
    23     @Override
    24     public void cry() {    //通知方法
    25         System.out.print("猫叫:");
    26         System.out.println("喵喵喵");
    27         for(Observer obs:observers) {
    28             obs.response();
    29         }
    30     }
    31 }

    具体观察者:Dog.java

     1 package com.nick.pattern.observer;
     2 /**
     3  * @ 具体观察者: 狗
     4  * @author nick
     5  *
     6  */
     7 public class Dog  implements Observer{
     8 
     9     @Override
    10     public void response() {
    11         System.out.print("狗叫:");
    12         System.out.println("汪汪汪");
    13     }
    14 
    15 }

    具体观察者:Mouse.java

     1 package com.nick.pattern.observer;
     2 /**
     3  * @ 具体观察者:老鼠
     4  * @author nick
     5  *
     6  */
     7 public class Mouse implements Observer{
     8 
     9     @Override
    10     public void response() {
    11         System.out.print("老鼠跑:");
    12         System.out.println("跑跑跑");
    13     }
    14 
    15 }

    主程序:Application.java

     1 package com.nick.pattern.observer;
     2 /**
     3  * @ 主程序
     4  * @author nick
     5  *
     6  */
     7 public class Application {
     8 
     9     public static void main(String[] args) {
    10             Subject cat = new Cat();
    11             Observer dog = new Dog();
    12             Observer mouse = new Mouse();
    13             cat.attach(dog);
    14             cat.attach(mouse);
    15             
    16             cat.cry();//触发通知方法
    17     }
    18 
    19 }

    运行结果:

      

     4、观察者模式的优缺点

    • 优点1: 具体主题和观察者是松耦合的关系。由于主题接口仅仅依赖与观察者接口,因此具体主题只是知道他的观察者是实现观察者接口的某个类的实例,但不需要知道是哪个类。
    • 优点2:具体观察者只需要知道它依赖的主题是实现主题接口的某个实例即可,不需要知道具体是哪个类。
    • 优点3:观察者模式满足“开-闭”原则。主题接口(Subject)仅仅依赖于观察者接口(Observer)。这样具体主题的类也仅仅依赖于观察者接口,增加新的实现观察者接口的类,不必修改创建具体主题的类的代码:
      •   新增加一个观察者Pig.java
      •  1 package com.nick.pattern.observer;
         2 /**
         3  * @ 新增的观察者Pig
         4  * @author nick
         5  */
         6 public class Pig implements Observer{
         7 
         8     @Override
         9     public void response() {
        10         System.out.println("猪叫:");
        11         System.out.println("咯咯咯");
        12     }
        13 
        14 }
      • 只需要在主程序中添加这两行代码

     

     

     

  • 相关阅读:
    iOS很重要的 block回调
    怎样写具体设计文档
    ORM框架
    RapidXml用法
    【Android Training
    ORACLE触发器具体解释
    LeetCode 131 Palindrome Partitioning
    Git管理工具对照(GitBash、EGit、SourceTree)
    Android下将图片载入到内存中
    怎样破解邮箱password
  • 原文地址:https://www.cnblogs.com/sinlearn/p/11882048.html
Copyright © 2011-2022 走看看