【行为型模式】观察者模式

devtools/2024/10/22 14:31:27/

一、观察者模式概述​

        软件系统其实有点类似观察者模式,目的:一个对象的状态或行为的变化将导致其他对象的状态或行为也发生改变,他们之间将产生联动

        观察者模式属于对象行为型

  •         1.定义了对象之间一种一对多的依赖关系,让一个对象的改变能够影响其他对象。
  •         2.发生改变的对象称为观察目标,被通知的对象成为观察者。
  •         3.一个观察目标可以对应多个观察者。别名:发布-订阅(Public/subscribe)模式,模型-视图(Model/View)模式,源-监听器(Source/Listener)模式,从属者(Dependents)模式。

        观察模式的优缺点

  •         优点
    • 1.可以实现表示层和数据逻辑层的分离。
    • 2.在观察目标和观察者之间建立了一个抽象的耦合。
    • 3.支持广播通信,简化了一对多系统设计的难度。
    • 4.符合开闭原则,添加新的具体观察者无须修改与原有系统代码,在具体观察者与观察目标之间不存在关联关系的情况下,增加新的观察目标也很方便。
  •         缺点
    • 1.将所有的观察者都通知到会花费很多时间。
    • 2.如果存在循环依赖时可能会导致系统崩溃。
    • 3.没有相应得机制让观察者知道所观察得目标对象是怎么发生变化得,而只是知道观察目标发生了变化。
  •         适用环境
    • 1.一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将两个方面封装在独立得对象中方使它们可以各自独立地改变和复用。
    • 2.一个对象的改变将导致一个或多个其他对象发生改变,且并不知道具体有多少个对象将发生改变,也不知道这些对象是谁。
    • 3.需要在系统中创建一个触发链。

二、代码实现

  主题(Subject)+观察者(Observer)=观察者模式

        观察者模式的代码结构包含

  • 抽象主题(Subject):接口,抽象类;
  • 具体主题(ConcreteSubject):比如公众号;
  • 抽象观察者(Observer);
  • 具体观察者(ConcreteObserver);
        2.1 战队控制实现代码
        2.1.1 抽象主题用抽象类实现(抽象类类名AllyControlCenter)
java">package Observe.ally;import java.util.*;//战队控制中心类:目标抽象类
public abstract class AllyControlCenter {protected String allyName;//战队名称//定义一个玩家集合protected ArrayList<Observer> players =new ArrayList<Observer>();public String getAllyname() {return allyName;}public void setAllyname(String allyName) {this.allyName = allyName;}//注册方法public void join(Observer obs) {System.out.println(obs.getName()+"加入"+this.allyName+"战队!");players.add(obs);}//注销方法public void quit(Observer obs) {System.out.println(obs.getName()+"退出"+this.allyName+"战队!");players.remove(obs);}//声明抽象通知方法public abstract void notifyObserver(String name);
}
        2.1.2 具体主题实现(ConcreteAllyControlCenter)
java">package Observe.ally;public class ConcreteAllyControlCenter extends AllyControlCenter {public ConcreteAllyControlCenter(String allyName) {System.out.println(allyName+"战队组建成功!");System.out.println("-------------------------");this.allyName = allyName;}@Overridepublic void notifyObserver(String name) {// TODO 自动生成的方法存根System.out.println(this.allyName+"战队紧急通知,盟友"+name+"遭受敌人袭击!");//遍历观察者集合,调用每一个盟友(自己除外)的支援方法for(Object obs : players) {if(!((Observer)obs).getName().equalsIgnoreCase(name)) {((Observer)obs).help();}}}}
        2.1.3 抽象观察类(接口实现,接口名为Observer)
java">package Observe.ally;
//抽象观察类
public interface Observer {public String getName();public void setName(String name);public void help();//声明支援盟友方法//声明遭受攻击方法public void beAttacked(AllyControlCenter acc);
}
        2.1.4 具体观察者(Player)
java">package Observe.ally;public class Player implements Observer{private String name;public Player(String name) {this.name =name;}public String getName() {return name;}public void setName(String name) {this.name = name;}//支援盟友方法的实现public void help() {System.out.println("坚持住:"+this.name+"来救你!");}//遭受攻击方法的实现,当遭受攻击时将调用战队控制中心的通知方法notifyObserver()来通知public void beAttacked(AllyControlCenter acc) {System.out.println(this.name+"被攻击!");acc.notifyObserver(name);}
}
        2.1.5 main方法调用实现观察者模式
java">package Observe.ally;public class Client {public static void main(String[] args) {// TODO 自动生成的方法存根//定义观察者目标对象AllyControlCenter acc;acc= new ConcreteAllyControlCenter("金庸群侠");//定义四个观察者对象Observer player1,player2,player3,player4;player1 = new Player("杨过");acc.join(player1);player2 = new Player("令狐冲");acc.join(player2);player3 = new Player("张无忌");acc.join(player3);player4 = new Player("段誉");acc.join(player1);//某成员遭受攻击player1.beAttacked(acc);}}
        2.1.6 UML图

        2.2 公众号代码实现
        2.2.1 抽象主题用抽象接口实现(抽象接口名Subject)
java">package Observe.Weixin_observation;
//公众号,主题对象
public interface Subject {//注册public void registerObserver(Observer o);//删除public void removeObserver(Observer o);//通知用户public void notifyObservers(String message);
}
        2.2.2 具体主题实现(WeixinSubject
java">package Observe.Weixin_observation;import java.util.*;public class WeixinSubject implements Subject {private List<Observer> users = new ArrayList<Observer>();String msg;@Overridepublic void registerObserver(Observer o) {// TODO 自动生成的方法存根users.add(o);}@Overridepublic void removeObserver(Observer o) {// TODO 自动生成的方法存根int i = users.indexOf(o);if(i>=0)users.remove(i);}@Overridepublic void notifyObservers(String message) {// TODO 自动生成的方法存根//冒号表示范围==Observer必须在users里面for(Observer o:users) {o.update(message);}}//更新信息public void setMsg(String msg) {this.msg = msg;notifyObservers(msg);}
}
        2.2.3 抽象观察类(接口实现,接口名为Observer)
java">package Observe.Weixin_observation;public interface Observer {//发送文本信息,推送public void update(String message);
}
        2.2.4 具体观察者(WeixinUser)
java">package Observe.Weixin_observation;public class WeixinUser implements Observer {String name;public WeixinUser(String name) {super();this.name = name;}@Overridepublic void update(String message) {// TODO 自动生成的方法存根System.out.println(name+",您好!"+message);}//关注/订阅公众号public void subscribeSubject(Subject o) {o.registerObserver(this);}//取消订阅public void deleteSubject(Subject o) {o.removeObserver(this);}
}
        2.2.5 main方法调用实现观察者模式
java">package Observe.Weixin_observation;public class Test {public static void main(String[] args) {// TODO 自动生成的方法存根//创建一个微信公众号WeixinSubject hdjdlgxydxfy = new WeixinSubject();WeixinUser user1 = new WeixinUser("user1");WeixinUser user2 = new WeixinUser("user2");WeixinUser user3 = new WeixinUser("user3");//用户关注user1.subscribeSubject(hdjdlgxydxfy);user2.subscribeSubject(hdjdlgxydxfy);user3.subscribeSubject(hdjdlgxydxfy);//推送消息hdjdlgxydxfy.setMsg("学院2020年体育课开始选课拉.....");//取消订阅user1.deleteSubject(hdjdlgxydxfy);hdjdlgxydxfy.setMsg("学院2020年体育课结束,下面是选课名单...");}}
        2.2.6 UML图

三、代码结构图


http://www.ppmy.cn/devtools/6241.html

相关文章

aws云靶场和一些杂记

aws靶场 在AWS靶场中&#xff0c;存在三个安全问题&#xff1a;1) 一个S3存储桶政策配置错误&#xff0c;允许公共访问&#xff0c;通过访问特定域名可获取flag。2) SQS消息队列的政策没有限制角色&#xff0c;允许发送和接收消息&#xff0c;通过aws sqs命令行工具的receive-…

机器学习周报第35周SE-LSTM

文章目录 week35 SE-LSTM摘要Abstract一、文献阅读1. 题目2. abstract3. 网络架构3.1 Savitsky-Golay 滤波器3.2 模型结构——SE-LSTM 4. 文献解读4.1 Introduction4.2 创新点4.3 实验过程4.3.1 训练参数4.3.2 数据集4.3.3 实验设置4.3.4 实验结果 5. python环境下基于scipy实现…

李沐47_转置卷积

转置卷积 1.卷积不会增大输入的高宽&#xff0c;要么不变&#xff0c;要么减半 2.转置卷积可以用来增大输入高宽 3.用id卷积卷&#xff0c;增大卷积核的数量可以达到增大特征图的目的 import torch from torch import nn from d2l import torch as d2l输入矩阵X和卷积核矩阵…

利用 Python 开发手机 App 实战

Python语言虽然很万能&#xff0c;但用它来开发app还是显得有点不对路&#xff0c;因此用Python开发的app应当是作为编码练习、或者自娱自乐所用&#xff0c;加上目前这方面的模块还不是特别成熟&#xff0c;bug比较多&#xff0c;总而言之&#xff0c;劝君莫轻入。 准备工作 …

kafka实验部署

一、前期准备 二、kafka实验 在zookeeper后继续进行操作 2.1 为ndoe1、node2、node3作出部署 2.1.1 解压kafka压缩包&#xff08;node1举例&#xff09; 2.1.2 操作 将解压后的kafka移动到kafka&#xff0c;进入到kafka下的config中&#xff0c;复制文件 2.1.2.1 编辑server.pr…

【Qt】探索Qt框架:跨平台GUI开发的利器

文章目录 1. Qt框架概述1.1. Qt框架的优点1.2. Qt框架支持的系统1.3. Qt开发环境 2. 搭建 Qt 开发环境2.1. Qt SDK 的下载和安装2.2. 新建项目: 3. Qt 框架内容简介总结 在当今软件开发领域&#xff0c;跨平台性和用户界面的友好性是至关重要的。而Qt框架作为一款跨平台的C图形…

代码随想录算法训练营第四十八天|leetcode72、583题

一、leetcode第583题 本题要求删除两个单词中的字母使得剩余字母均相同&#xff0c;因此设置dp数组&#xff0c;dp[i][j]的含义是0-&#xff08;i-1&#xff09;个字母和0-&#xff08;j-1&#xff09;个字母相同时需要删除的最少次数。递推公式在word1[i-1]word2[j-1]时&…

浏览器工作原理与实践--HTTPS:让数据传输更安全

浏览器安全主要划分为三大块内容&#xff1a;页面安全、系统安全和网络安全。前面我们用四篇文章介绍了页面安全和系统安全&#xff0c;也聊了浏览器和Web开发者是如何应对各种类型的攻击&#xff0c;本文是我们专栏的最后一篇&#xff0c;我们就接着来聊聊网络安全协议HTTPS。…