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

           设计模式是一套被反复使用,多数人知晓,经过分类编目的,代码设计的总结,也可以说是前人的智慧结晶。学习设计模式能让我们对一些应用场景使用相同的套路达到很好的效果,我会不定时更新一些自己
      对设计模式的理解的文章,
    从定义,实现,应用场景来说说设计模式,今天我要说的对象是观察者模式
      一:定义
          观察者模式是应用最为广泛的设计模式之一
          观察者模式定义如下: 观察者模式(Observer Pattern):定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布-订阅
      (Publish/Subscribe)模式、
    模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。
          观察者模式通常由一下4个成员组成
          1.抽象的主题(Subject),或者称为抽象的被观察者,一般包含一个记录所有观察者对象的集合,一个添加观察者的方法attach(),一个删除观察者的方法detach(),一个通知抽象的方法notify().
          2.具体的主题ConcreteSubject,或者被称为具体的被观察者,实现notify方法,有的具体主题还要添加一个状态
          3.抽象的观察者Observer,主要提供一个抽象的update方法,有时候还需要和一个具体的主题实例相绑定
          4.具体的观察者ConcreteObserver,实现update方法,当具体观察者的状态变化时,调用这个方法
          
      二:实现
              这里以直播聊天室为例子实现观察者模式,在聊天室中,用户,服务中心刚好相当于观察者于观察的关系,当服务中心的信息有变化的时候,需要通知到所有用户,这里以用户上线和聊天聊个操作为例子说明问题,
            这里把用户的发送和接收两个操作分成两个抽象,被一个观察者执行,比如用户需要向服务台发送登录操作,发送成功后,其他聊天室的成功观察到服务台的变化,需要进行相应。发送和接收的操作都抽象出来之后,
            后续添加新的功能,比如发送,接收语音
    /**
    * 抽象主题
    */
    abstract class Subjects {

    public static List<Observer> observerList = new ArrayList();

    /**
    * 添加观察者
    */
    public void attach(Observer observer) {
    observerList.add(observer);
    }

    /**
    * 移除观察者
    */
    protected void detach(Observer observer) {
    observerList.remove(observer);
    }

    /**
    * 通知
    */
    public abstract void allNotify(String msg);

    }

    /**
    * 上线操作
    */
    class LoginSubject extends Subjects {
    /**
    * 添加观察者
    */
    @Override
    public void attach(Observer observer) {
    super.attach(observer);
    String msg = observer.getName() + "上线了........";
    allNotify(msg);

    }

    @Override
    public void allNotify(String msg) {
    LoginDispose loginDispose = new LoginDispose();
    for (Observer observer : observerList) {
    loginDispose.setMessage(observer.getName() + "收到信息:" + msg);
    observer.update(loginDispose);
    }
    }
    }



    /**
    * 聊天
    */
    class ChatSubject extends Subjects {

    @Override
    public void allNotify(String msg) {
    ChatDispose characterDispose = new ChatDispose();
    for (Observer observer : observerList) {
    characterDispose.setMessage(observer.getName() + "收到信息 " + msg);
    observer.update(characterDispose);
    }
    }
    }


    /**
    * 抽象观察者
    */
    abstract class Observer {
    public String name;
    abstract void update(Dispose dispose);
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    }

    /**
    * 具体观察者,用户
    */
    class UserObserver extends Observer {
    public UserObserver(String name) {
    super.name = name;
    }
    @Override
    void update(Dispose dispose) {
    dispose.operation();
    }

    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    }

    /**
    * 抽象用户的接收操作
    */
    abstract class Dispose {
    public String message;

    /**
    * 抽象操作的方法
    */
    abstract void operation();

    public String getMessage() {
    return message;
    }
    public void setMessage(String message) {
    this.message = message;
    }
    }


    /**
    * 接收聊天操作的实现
    */
    class ChatDispose extends Dispose {
    @Override
    void operation() {
    System.out.println(this.message);
    }
    }

    /**
    * 接收接受登录操作的实现
    */
    class LoginDispose extends Dispose {
    @Override
    void operation() {
    System.out.println(this.message);
    }
    }


    /**
    * 发送操作的抽象
    */
    abstract class Handle {
    protected UserObserver userObserver;

    /**
    * 抽象操作方法
    */
    abstract void operation();
    }

    /**
    * 发送聊天操作的实现
    */
    class ChatHandle extends Handle {
    private String message;

    public ChatHandle(UserObserver userObserver, String message) {
    this.userObserver = userObserver;
    this.message = message;
    }

    @Override
    void operation() {
    this.message = userObserver.getName() + "说:" + this.message;
    Subjects subject = new ChatSubject();
    subject.allNotify(this.message);
    }

    }


    /**
    * 测试方法
    */
    class test {
    public static void main(String[] fdfd) {
    /**
    * 实例化登录主题
    */
    Subjects loginSubjects = new LoginSubject();
    /**
    * 欧阳锋上线
    */
    UserObserver ouyangfeng = new UserObserver("欧阳锋");
    loginSubjects.attach(ouyangfeng);

    /**
    * 洪七公上线
    */
    UserObserver hongqigong = new UserObserver("洪七公");
    loginSubjects.attach(hongqigong);

    /**
    * 黄药师上线
    */
    UserObserver huangyaos = new UserObserver("黄药师");
    loginSubjects.attach(huangyaos);

    /**
    * 一灯大师上线
    */
    UserObserver yideng = new UserObserver("一灯大师");
    loginSubjects.attach(yideng);

    /**
    * 欧阳锋发言
    */
    Handle chatHandle = new ChatHandle(ouyangfeng, "今年华山之上,和各位一争高低");
    chatHandle.operation();

    }

    }

        打印结果:
          

    欧阳锋收到信息:欧阳锋上线了........
    欧阳锋收到信息:洪七公上线了........
    洪七公收到信息:洪七公上线了........
    欧阳锋收到信息:黄药师上线了........
    洪七公收到信息:黄药师上线了........
    黄药师收到信息:黄药师上线了........
    欧阳锋收到信息:一灯大师上线了........
    洪七公收到信息:一灯大师上线了........
    黄药师收到信息:一灯大师上线了........
    一灯大师收到信息:一灯大师上线了........
    欧阳锋收到信息
    欧阳锋说:今年华山之上,和各位一争高低
    洪七公收到信息
    欧阳锋说:今年华山之上,和各位一争高低
    黄药师收到信息
    欧阳锋说:今年华山之上,和各位一争高低
    一灯大师收到信息
    欧阳锋说:今年华山之上,和各位一争高低


      三:应用场景

        在以下情况下可以考虑使用观察者模式:
          (1) 一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两个方面封装在独立的对象中使它们可以各自独立地改变和复用。

                (2) 一个对象的改变将导致一个或多个其他对象也发生改变,而并不知道具体有多少对象将发生改变,也不知道这些对象是谁

          (3) 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。


















  • 相关阅读:
    dpdk 连接错误
    strace 跟踪文件
    鲲鹏服务器 centos 升级gcc + 安装qemu
    centos 升级gcc
    undefined reference to `shm_open'
    Golang与C互用
    [ TIME ] Timed out waiting for device dev-ttyS0.device. [DEPEND] Dependency failed for Serial Getty on ttyS0.
    大型 Web 应用插件化架构探索
    网易游戏基于 Flink 的流式 ETL 建设
    基于WASM的无侵入式全链路A/B Test实践
  • 原文地址:https://www.cnblogs.com/farmer-lau/p/10194216.html
Copyright © 2011-2022 走看看