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

一、观察者模式概述​

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

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

  •         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)
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)
package Observe.ally;

public class ConcreteAllyControlCenter extends AllyControlCenter {
	public ConcreteAllyControlCenter(String allyName) {
		System.out.println(allyName+"战队组建成功!");
		System.out.println("-------------------------");
		this.allyName = allyName;
	}
	@Override
	public 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)
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)
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方法调用实现观察者模式
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)
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
package Observe.Weixin_observation;

import java.util.*;

public class WeixinSubject implements Subject {
	private List<Observer> users = new ArrayList<Observer>();
	String msg;
	@Override
	public void registerObserver(Observer o) {
		// TODO 自动生成的方法存根
		users.add(o);
	}

	@Override
	public void removeObserver(Observer o) {
		// TODO 自动生成的方法存根
		int i = users.indexOf(o);
		if(i>=0)
			users.remove(i);
	}

	@Override
	public 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)
package Observe.Weixin_observation;

public interface Observer {
	//发送文本信息,推送
	public void update(String message);
}
        2.2.4 具体观察者(WeixinUser)
package Observe.Weixin_observation;

public class WeixinUser implements Observer {
	String name;
	public WeixinUser(String name) {
		super();
		this.name = name;
	}
	@Override
	public 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方法调用实现观察者模式
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图

三、代码结构图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/550686.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

翱途O2OA新手上路-服务器下载及私有云部署

本篇主要简要描述从官网下载服务器&#xff0c;进行部署&#xff0c;启动的过程&#xff0c;并且描述在部署过程中常见的问题与报错以及云服务器安全策略配置和O2OA服务器端口修改的方式。 O2OA部署的服务器要求不高&#xff0c;一般使用4C8G以上的服务器均可正常运行。 一、检…

锂电池充放电管理-单片机通用

锂电池充放电管理-单片机通用 一、锂电池充放电检测的原理二、power.c的实现三、power.h的实现四、锂电池检测和充电电路 一、锂电池充放电检测的原理 ①两节锂电池通过电阻分压检测ADC&#xff0c;再根据电压划分电量等级&#xff1b;②充电使用的是锂电池充电IC方案&#xf…

2024年4月最新版GPT

2024年4月最新版ChatGPT/GPT4, 附上最新的使用教程。 随着人工智能技术的不断发展&#xff0c;ChatGPT和GPT4已经成为了人们日常生活中不可或缺的助手。2024年4月,OpenAI公司推出了最新版本的GPT4,带来了更加强大的功能和更加友好的用户体验。本文将为大家带来最新版GPT4的实用…

每日一题(PTAL2-006):树的遍历--树的构建,队列

因为要层序遍历&#xff0c;所以我们可以考虑构建一颗二叉树。构建完只有利用队列就可以就行层序遍历。 #include <bits/stdc.h> using namespace std; int p1[35]; int p2[35]; typedef struct Tree {int val;struct Tree* left;struct Tree* right; }TT; typedef TT* …

鸿蒙入门02-首次安装和配置

注&#xff1a;还没有安装编辑器&#xff08; deveco studio &#xff09;的小伙伴请看鸿蒙入门01-下载和安装-CSDN博客 首次安装配置 编辑器&#xff08; deveco studio &#xff09;安装完毕以后需要进入配置界面进行相关配置配置完毕以后才可以正常使用 环境配置&#xf…

微信小程序全局配置

全局配置文件及常用的配置项 小程序根目录下的 app.json 文件是小程序的全局配置文件。常用的配置项如下&#xff1a; ① pages 记录当前小程序所有页面的存放路径 ② window 全局设置小程序窗口的外观 ③ tabBar 设置小程序底部的 tabBar 效果 ④ style 是否启用新版的组件样…

MongoDB的CURD(增删改查操作)

读者大大们好呀&#xff01;&#xff01;!☀️☀️☀️ &#x1f525; 欢迎来到我的博客 &#x1f440;期待大大的关注哦❗️❗️❗️ &#x1f680;欢迎收看我的主页文章➡️寻至善的主页 ✈️如果喜欢这篇文章的话 &#x1f64f;大大们可以动动发财的小手&#x1f449;&#…

【IT运维入门(ITHW)系列】之「快速部署」第二期清单(持续更新)

ITHW是Information Technology Hello World的缩写简拼。意在提供IT领域的入门相关知识&#xff0c;近期给大家带来的是主流技术选型的快速部署系列&#xff0c;意在最大程度地简化部署过程&#xff0c;以便能快速体验或测试相关技术选型。 「快速部署」第一期清单 ITHW快捷部署…

Day 15 Linux网络管理

IP解析 IP地址组成&#xff1a;IP地址由4部分数字组成&#xff0c;每部分数字对应于8位二进制数字&#xff0c;各部分之间用小数点分开&#xff0c;这是点分2进制。如果换算为10进制我们称为点分10进制。 每个ip地址由两部分组成网络地址(NetID)和主机地址(HostID).网络地址表…

文件服务: txt文件预览乱码问题

文章目录 一、背景二、解决方案1、转换流&#xff08;解决代码与文件编码不一致读取乱码的问题&#xff09;2、获取文本文件的字符编码 一、背景 在springboot项目中使用springmvc web.resources的形式进行文件访问。本地上传txt文件编码格式为GB2312(中文简体)&#xff0c;浏…

大数据平台搭建2024(二)

二&#xff1a;Hive安装 只在node01上操作 1 安装MySQL 8.0 最小化安装需要安装这个 yum install -y wget1-1 下载MySQL的yum源 wget http://dev.mysql.com/get/mysql80-community-release-el7-7.noarch.rpm检查是否安装成功 rpm -qpl mysql80-community-release-el7-7.n…

什么是漏洞?最全的漏洞分类!

01 — “ 什么是漏洞**”** 漏洞是指一个系统存在的弱点或缺陷&#xff0c;系统对特定威胁攻击或危险事件的敏感性&#xff0c;或进行攻击的威胁作用的可能性。漏洞可能来自应用软件或操作系统设计时的缺陷或编码时产生的错误&#xff0c;也可能来自业务在交互处理过程中的设…

14.C++常用的算法_排序算法

文章目录 遍历算法1. sort()代码工程运行结果 2. random_shuffle()代码工程运行结果第一次运行结果第二次运行结果第三次运行结果 3. merge()代码工程运行结果 4. reverse()代码工程运行结果 遍历算法 1. sort() 代码工程 sort()函数默认是升序排列&#xff0c;如果想要降序…

ChatGPT实用指南2024

随着ChatGPT技术的演进&#xff0c;越来越多的人开始在工作中利用此工具。以下是关于ChatGPT的实用指南&#xff0c;适合不太熟悉此技术的朋友参考。 一、ChatGPT概述 1. ChatGPT是什么&#xff1f; ChatGPT是基于OpenAI开发的GPT大型语言模型的智能对话工具。它能够通过自然语…

爆肝3k字!掌握Spring与Redis的高效交互:从Jedis到Spring Data Redis

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

B203-若依框架应用

目录 简介版本RuoYi-fast项目准备新增模块/代码生成 简介 基于SpringBoot的权限管理系统&#xff0c;基于SpringBoot开发的轻量级Java快速开发框架 版本 前后端未分离单应用版本&#xff1a;RuoYi-fast&#xff0c;前后端未分离多模块版本&#xff1a;RuoYi 前后端分离单应用…

06节-51单片机-LCD1602调试工具

欢迎订阅专栏&#xff0c;持续为您更新&#xff01; 1.LCD1602调试工具 使用LCD1602液晶屏作为调试窗口&#xff0c;提供类似printf函数的功能&#xff0c;可实时观察单片机内部数据的变换情况&#xff0c;便于调试和演示。 本文提供的LCD1602代码属于模块化的代码&#xff…

Java如何用EasyExcel插件对Excel进行数据导入和数据导出

文章目录 一、EasyExcel的示例导入依赖创建实体类数据导入和导出 二、EasyExcel的作用三、EasyExcel的注解 EasyExcel是一个阿里巴巴开源的excel处理框架&#xff0c;它以使用简单、节省内存著称。在解析Excel时&#xff0c;EasyExcel没有将文件数据一次性全部加载到内存中&…

如果补货机器人也开始搬砖

过去几年&#xff0c;如果一位顾客的欲购商品疑似缺货&#xff0c;“请稍等&#xff0c;我去后台查一下”便是最常听到的一句话。随着过去几年劳动力短缺的加剧&#xff0c;货架并不总像许多人习惯的那样满满当当。为减轻不断补货的负担&#xff0c;使员工可以将精力集中于其他…

【AI工具】AI一键生成思维导图

ChatMind 被 Xmind 收购之后&#xff08;即那个 00 后团队&#xff09;&#xff0c;将重点聚焦于海外市场&#xff0c;国内职场用户可对其予以关注&#xff0c;用户体验着实不错&#xff08;我认为 AI 生成思维导图&#xff0c;其关键点在于交互与 UI&#xff09;&#xff1a; …