当前位置: 首页 > 编程日记 > 正文

步步为营-44-窗体之间传值--观察者模式

说明 :观察者模式又叫发布-订阅模式,其中又涉及到中介者模式

1 结构

2 创建Main窗体(中介者),ChildForm1(发布者),ChildForm2(订阅者),ChildForm3(订阅者),

2.1 ChildForm1中添加按钮,当按钮被点击是ChildForm2(订阅者),ChildForm3(订阅者),的文本框汇中获取信息

2.2 定义接口

public interface IMessageOn
     {
         void RecieveMsg(string str);
     }

2.3 在发布者ChildForm1中创建MessageOnList集合

2.4 订阅者ChildForm2,ChildForm3中实现接口

public void RecieveMsg(string str)
        {
            this.txtGetTime.Text = str;
        }

2.5 中介者Main把 订阅者放入到发布者的MessageONList集合中

ChildForm2 frm2 = new ChildForm2();
            //2把订阅者放入到发布者的MessageONList集合中
            frm1.MessageOnList.Add(frm2);
            //3显示窗体
            frm2.Show();

2.6 遍历集合,通知所有的观察者

foreach (var MessageOn in MessageOnList)
            {
                MessageOn.RecieveMsg(txtSendMsg.Text);
            }

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace 中介者_订阅者
{public partial class Main : Form{public Main(){InitializeComponent();}private void btnOpenForm_Click(object sender, EventArgs e){//1创建窗体ChildForm1 frm1 = new ChildForm1();frm1.Show();ChildForm2 frm2 = new ChildForm2(); //2把订阅者放入到发布者的MessageONList集合中
            frm1.MessageOnList.Add(frm2);//3显示窗体
            frm2.Show();ChildForm3 frm3 = new ChildForm3();frm1.MessageOnList.Add(frm3);frm3.Show();}}
}
Main
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace 中介者_订阅者
{public interface IMessageOn{void RecieveMsg(string str);}
}
IMessageOn
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace 中介者_订阅者
{public partial class ChildForm1 : Form{public ChildForm1(){InitializeComponent();MessageOnList = new List<IMessageOn>();}public List<IMessageOn> MessageOnList { set; get; }private void btnSendTime_Click(object sender, EventArgs e){foreach (var MessageOn in MessageOnList){MessageOn.RecieveMsg(txtSendMsg.Text);}}}
}
ChildForm1
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace 中介者_订阅者
{public partial class ChildForm2 : Form,IMessageOn{public ChildForm2(){InitializeComponent();}public void RecieveMsg(string str){this.txtGetTime.Text = str;}}
}
ChildForm2
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace 中介者_订阅者
{public partial class ChildForm3 : Form,IMessageOn{public ChildForm3(){InitializeComponent();}public void RecieveMsg(string str){this.txtGetTime.Text = str;}
}
}
ChildForm3

通过中介者,将发布者和订阅者实现了解耦

3 通过委托实现

3.1 在ChildForm1中声明委托类型

public delegate void SendMsgDel(string sendMsg);

3.2 在ChildForm1中定义委托实例

//02-02定义委托实例
        public SendMsgDel SendMsgDelInstance { set; get; }

3.3   在ChildForm2中定义委托实现方法
        public void RecieveMsgByDel(string str)
        {
            this.txtGetTime.Text = str;
        }

3.4 Main中将观察者的方法注册到ChildForm1中的委托中去

frm1.SendMsgDelInstance += frm2.RecieveMsgByDel;
 3.5 单击按钮触发事件

private void btnDelegate_Click(object sender, EventArgs e)
        {
            SendMsgDelInstance(txtSendMsg.Text);
        }

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace 中介者_订阅者
{public partial class Main : Form{public Main(){InitializeComponent();}private void btnOpenForm_Click(object sender, EventArgs e){//1创建窗体ChildForm1 frm1 = new ChildForm1();frm1.Show();ChildForm2 frm2 = new ChildForm2(); //2把订阅者放入到发布者的MessageONList集合中
            frm1.MessageOnList.Add(frm2);frm1.SendMsgDelInstance += frm2.RecieveMsgByDel;//3显示窗体
            frm2.Show();ChildForm3 frm3 = new ChildForm3();frm1.MessageOnList.Add(frm3);//2-2将观察者的方法注册到委托中去frm1.SendMsgDelInstance += frm3.RecieveMsgByDel;frm3.Show();}}
}
Main
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace 中介者_订阅者
{public interface IMessageOn{void RecieveMsg(string str);}
}
IMessageOn
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace 中介者_订阅者
{//02-01定义委托public delegate void SendMsgDel(string sendMsg);public partial class ChildForm1 : Form{public ChildForm1(){InitializeComponent();MessageOnList = new List<IMessageOn>();}#region 01通过发布者模式实现public List<IMessageOn> MessageOnList { set; get; }private void btnSendTime_Click(object sender, EventArgs e){foreach (var MessageOn in MessageOnList){MessageOn.RecieveMsg(txtSendMsg.Text);}} #endregion#region 02通过委托实现//02-02定义委托实例public SendMsgDel SendMsgDelInstance { set; get; }private void btnDelegate_Click(object sender, EventArgs e){SendMsgDelInstance(txtSendMsg.Text);} #endregion}
}
ChildForm1
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace 中介者_订阅者
{public partial class ChildForm2 : Form,IMessageOn{public ChildForm2(){InitializeComponent();}#region 01接口实现发布者模式 方法public void RecieveMsg(string str){this.txtGetTime.Text = str;} #endregion#region 02委托实现方法public void RecieveMsgByDel(string str){this.txtGetTime.Text = str;}#endregion}
}
ChildForm2
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace 中介者_订阅者
{public partial class ChildForm3 : Form,IMessageOn{public ChildForm3(){InitializeComponent();}#region 01接口实现发布者模式 方法public void RecieveMsg(string str){this.txtGetTime.Text = str;}#endregion#region 02委托实现方法public void RecieveMsgByDel(string str){this.txtGetTime.Text = str;}#endregion
}
}
ChildForm3

但是,使用委托有一缺陷==>不安全,
例如,在Main中创建完窗体后直接加一句

frm1.SendMsgDelInstance("委托实现不安全");

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace 中介者_订阅者
{public partial class Main : Form{public Main(){InitializeComponent();}private void btnOpenForm_Click(object sender, EventArgs e){//1创建窗体ChildForm1 frm1 = new ChildForm1();frm1.Show();ChildForm2 frm2 = new ChildForm2(); //2-1把订阅者放入到发布者的MessageONList集合中---接口形式注册
            frm1.MessageOnList.Add(frm2);frm1.SendMsgDelInstance += frm2.RecieveMsgByDel;frm1.SendMsgDelEven += frm2.RecieveMsgByEvent;//3显示窗体
            frm2.Show();ChildForm3 frm3 = new ChildForm3();frm1.MessageOnList.Add(frm3);//2-2将观察者的方法注册到委托中去----委托形式注册frm1.SendMsgDelInstance += frm3.RecieveMsgByDel;//2-3将观察者的方法注册到事件中去----事件形式注册frm1.SendMsgDelEven += frm3.RecieveMsgByEvent;frm3.Show();frm1.SendMsgDelInstance("委托实现不安全");//frm1.SendMsgDelEven("事件事件安全");
        }}
}
View Code

4通过事件实现

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace 中介者_订阅者
{public partial class Main : Form{public Main(){InitializeComponent();}private void btnOpenForm_Click(object sender, EventArgs e){//1创建窗体ChildForm1 frm1 = new ChildForm1();frm1.Show();ChildForm2 frm2 = new ChildForm2(); //2-1把订阅者放入到发布者的MessageONList集合中---接口形式注册
            frm1.MessageOnList.Add(frm2);frm1.SendMsgDelInstance += frm2.RecieveMsgByDel;frm1.SendMsgDelEven += frm2.RecieveMsgByEvent;//3显示窗体
            frm2.Show();ChildForm3 frm3 = new ChildForm3();frm1.MessageOnList.Add(frm3);//2-2将观察者的方法注册到委托中去----委托形式注册frm1.SendMsgDelInstance += frm3.RecieveMsgByDel;//2-3将观察者的方法注册到事件中去----事件形式注册frm1.SendMsgDelEven += frm3.RecieveMsgByEvent;frm3.Show();frm1.SendMsgDelInstance("委托实现不安全");//frm1.SendMsgDelEven("事件事件安全");
        }}
}
Main
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace 中介者_订阅者
{public interface IMessageOn{void RecieveMsg(string str);}
}
IMessageOn
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace 中介者_订阅者
{//02-01定义委托public delegate void SendMsgDel(string sendMsg);public partial class ChildForm1 : Form{public ChildForm1(){InitializeComponent();MessageOnList = new List<IMessageOn>();}#region 01通过发布者模式实现public List<IMessageOn> MessageOnList { set; get; }private void btnSendTime_Click(object sender, EventArgs e){foreach (var MessageOn in MessageOnList){MessageOn.RecieveMsg(txtSendMsg.Text);}} #endregion#region 02通过委托实现//02-02定义委托实例public SendMsgDel SendMsgDelInstance { set; get; }private void btnDelegate_Click(object sender, EventArgs e){SendMsgDelInstance(txtSendMsg.Text);} #endregion#region 03事件实现public event SendMsgDel SendMsgDelEven;private void btnEvent_Click(object sender, EventArgs e){if (SendMsgDelEven!=null){SendMsgDelEven(txtSendMsg.Text);}}#endregion}
}
ChildForm1
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace 中介者_订阅者
{public partial class ChildForm2 : Form,IMessageOn{public ChildForm2(){InitializeComponent();}#region 01接口实现发布者模式 方法public void RecieveMsg(string str){this.txtGetTime.Text = str;} #endregion#region 02委托实现方法public void RecieveMsgByDel(string str){this.txtGetTime.Text = str;}#endregion#region 03事件实现方法public void RecieveMsgByEvent(string str){this.txtGetTime.Text = str;}#endregion}
}
ChildForm2
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace 中介者_订阅者
{public partial class ChildForm3 : Form,IMessageOn{public ChildForm3(){InitializeComponent();}#region 01接口实现发布者模式 方法public void RecieveMsg(string str){this.txtGetTime.Text = str;}#endregion#region 02委托实现方法public void RecieveMsgByDel(string str){this.txtGetTime.Text = str;}#endregion#region 03事件实现方法public void RecieveMsgByEvent(string str){this.txtGetTime.Text = str;}#endregion
}
}
View Code

转载于:https://www.cnblogs.com/YK2012/p/6806842.html

相关文章:

java指令详解

Java是通过java虚拟机来装载和执行编译文件&#xff08;class文件&#xff09;的&#xff0c;java虚拟机通过命令java option 来启动&#xff0c;-option为虚拟机参数&#xff0c;通过这些参数可对虚拟机的运行状态进行调整. 一、如何查看参数列表: 虚拟机参数分为基本和扩展两…

wrs-arcface虹软人脸识别

前言 虹软人脸识别组件&#xff0c;支持活体识别、离线识别、图片人脸特征识别、图片是否同一人对比、相机人脸识别或对比,虹软免费版请使https://ext.dcloud.net.cn/plugin?id6084 功能 支持活体识别、离线识别图片人脸特征识别(年龄、性别、3DAngle)两张图片是否是同一人…

C++指针与引用的区别

&#xff08;1&#xff09;指针是一个变量&#xff0c;本身占有内存&#xff0c;内存中存储的是所指向对象的地址。引用是内存的别名。 &#xff08;2&#xff09;指针可以通过解引用的方式&#xff0c;取出所指向内存中的值。引用没有解引用。 &#xff08;3&#xff09;指针可…

Linux08-日志

目录 一、systemd的日志 1.1、sytemd-journald与systemd日志 1.2、systemd日志的持久化 二、系统常规日志 2.1、系统日志概述 2.2、查看系统日志文件 2.3、日志的轮转 2.4、分析系统日志 2.5、使用logger发送消息到日志 RHEL7的日志由2个服务负责记录&#xff0c;分别…

Java的小实验——各种测试以及说明

日期&#xff1a;2018.10.07 星期五 博客期&#xff1a;014 一、Java中的位运算 代码如下&#xff1a; 1 package Morts107;2 3 public class Test107 {4 public static void main(String[] args) {5 int z;6 z 13>>1;//00001101(13)---------------…

C++内存的分区

C内存分为四个区&#xff1a; &#xff08;1&#xff09;代码区&#xff1a;存放代码转译成的二进制代码。 &#xff08;2&#xff09;全局区&#xff1a;存放全局变量、静态变量&#xff08;static&#xff09;、常量&#xff08;如字符串常量&#xff09;。 全局区中还包含一…

SpringCloud的服务网关zuul

演示如何使用api网关屏蔽各服务来源 一、概念和定义 1、zuul最终还是使用Ribbon的&#xff0c;顺便测试一下Hystrix断路保护2、zuul也是一个EurekaClient&#xff0c;访问服务注册中心&#xff0c;获取元数据&#xff0c;使用本地的Ribbon负载均衡&#xff0c;Hystrix断路保护&…

wrs-tuya-cloud

前言 wrs-tuya-cloud是涂鸦官网针对云开发的插件&#xff0c;包含垂直品类硬件API(万能红外开放能力、设备连接服务、设备OTA固件升级、实时音视频、睡眠带开放能力、体脂秤开放能力、智能门锁开放能力、视频云存储 、邮件服务 、 语音消息服务、消息推送服务、短信服务 、内测…

Windows Server 2016 笔记

从业界普遍实践结果来看&#xff0c;Windows Server在服务器领域真是不太好用。但是&#xff0c;有些时候由于种种原因不得不用&#xff0c;所以还是有必要了解一下的。今天参加了一个Windows Server的培训&#xff0c;主要面对Windows Server 2016&#xff0c;写下这篇博客备忘…

(办公)网页发送到桌面快捷方式怎么做

转载自百度:https://jingyan.baidu.com/article/f79b7cb303d50a9145023e6e.html 有时候一个网页我们需要经常用到&#xff0c;每次找那个需要的网页很耗时间&#xff0c;那么我们怎么把我们需要的网页发送到桌面快捷方式呢&#xff1f; 这样下次我们直接点击桌面上的快捷方式就…

C++程序编译过程

程序编译的过程&#xff0c;是将源代码转换为计算机可执行的机械语言的过程。分为预处理、编译、汇编、链接四步。 &#xff08;1&#xff09;预处理&#xff1a;对程序进行预处理&#xff0c;比如将头文件的代码直接赋值到当前代码中等等. &#xff08;2&#xff09;编译&am…

Java的注释(详细版)

注释是对代码进行必要的说明&#xff0c;以便于后期的修改、维护和升级。Java的注释分为三种&#xff1a;第一种是**单行注释**&#xff1a;用双斜杠“//”来进行实例&#xff1a;//单行注释第二种是**文档注释**&#xff1a;用斜杠“/”和星号“*”来进行实例&#xff1a;/***…

Hadoop的存储架构介绍

http://lxw1234.com/archives/2016/04/638.htm 该文章介绍了Hadoop的架构原理&#xff0c;简单易懂。 目前公司提供Hadoop的运算集群BMR&#xff0c;可以直接申请集群资源。转载于:https://www.cnblogs.com/blog-of-Fourier/p/6809811.html

编译OpenSSH8.4的RPM包及升级

目录 一、安装相关依赖包 二、创建rpmbuild目录并下载源码 三、打包及排错 四、升级到OpenSSH 8.4p1 以下是打包好的OpenSSH 8.4p1&#xff0c;包括7个rpm包&#xff0c;欢迎下载使用。 OpenSSH-8.4p1-Bundle 一、安装相关依赖包 根据以往经验&#xff0c;需要安装wget、…

centos 系统使用verdaccio搭建npm私库

.安装nodejs yum install -y nodejs 2.安装verdaccio npm install -g verdaccio --unsafe-perm 3.配置 a.修改配置文件 config.yaml&#xff0c;在其最后添加监听端口&#xff08;使其可在外网访问&#xff09; listen: 0.0.0.0:4873 b.对外开放4873端口 firewall-cmd --state …

视觉SLAM中PNP求解

PNP&#xff08;Perspective-n-points&#xff09;是SLAM中估计位姿的重要方法。已知条件为路标点在相机1中的相机坐标以及投影到相机2中的像素坐标&#xff0c;据此去估计相机1、相机2间的位姿。主要解法包括DLT、P3P、EPNP P3P 已知A、B、C在相机1坐标系下的坐标&#xff0…

Java程序的运行原理 用记事本编写Java代码

首先将Java代码写入源文件(.java)中→ 通过 javac 生成class文件(.class) → 再通过java命令执行程序&#xff1a;◆将class文件加载内存&#xff08;相当于将东西输入大脑&#xff09;◆检验class文件&#xff08;大脑检查是否有语法等错误&#xff0c;若无误&#xff09;◆将…

Linux下修改mysql的root密码后数据库消失怎么处理

Linux系统下如果没有通过password&#xff08;&#xff09;函数修改mysql的root密码就会导致mysql数据库消失。有些人可能不知道而直接修改了mysql的root密码&#xff0c;于是产生了mysql数据库消失的问题&#xff0c;这个时候该怎么处理呢&#xff1f; 可以用下面的办法解决&a…

编译httpd-2.4.46的RPM包

目录 一、下载源码 二、编译&排错 2.1、第一次编译&#xff0c;解决依赖包问题。 2.2、第二次编译&#xff0c;解决anaconda导致的环境变量问题 2.3、第三次编译&#xff0c;解决apr版本过低问题 提供 apr-1.7.0、httpd-2.4.46 的RPM包下载。 apr-1.7.0-bundle.zip …

C/s模式B/S模式

C/s模式&#xff1a;是客户端/服务器(Client/Server)模式&#xff0c;主要指的是传统的桌面级的应用程序。比如我们经常用的信息管理系统。 C/S 客户端/服务器 例如QQ&#xff0c;网络游戏&#xff0c;需要下载客户端才能访问服务器的程序 B/S 浏览器/服务器 例如Intel&#xf…

分割catalina.out 每天生成一个文件

1. touch xxx(文件名字).sh 2. vim xxx.sh 写入 ----------------------- #!/bin/shcd dirname $0pwdddate %Y%m%dd7date -d7 day ago %Y%m%dcd ../logs/cp catalina.out catalina.out.${d}cat /dev/null > catalina.outrm -rf catalina.out.${d7} ----------…

、|| 和 、| 的区别(详尽版)

&&和|| 是逻辑运算符&#xff08;也包括 !&#xff09; 逻辑运算符含义&&逻辑与&#xff08;两者为真才为真&#xff0c;一者为假即为假&#xff09;︱︱逻辑或&#xff08;两者为假才为假&#xff0c;一者为真即为真&#xff09;!逻辑非&#xff08;本来值的…

C++负数、小数如何保存

负整数 正整数直接按照源码存储&#xff0c;负整数按照补码存储。 原码、反码、补码 首先要清楚原码、反码、补码&#xff1a; 计算机中一个字节为8位&#xff0c;在此以一个字节为例&#xff1a; 原码&#xff1a; 十进制1&#xff1a;0000 0001 十进制-1&#xff1a;1000 …

MySQL00-这都不知道还TM学啥MySQL

目录 一、MySQL架构概述 1.1、客户端连接器 1.2、连接层 1.3、可插拔存储引擎 1.4、文件系统与文件 二、配置文件 三、数据文件 四、日志文件&#xff08;以MySQL5.7.32为例&#xff09; 4.1、错误日志 Error Log 4.2、一般查询日志 General Query Log 4.3、二进制日…

ORB_SLAM2 PnPSolver

EPNP&#xff1a;已知4组&#xff08;默认&#xff09;3D-2D匹配点&#xff0c;构建参考点&#xff0c;通过计算参考点的相机坐标&#xff0c;线性组合成路标点的相机坐标。然后使用ICP估计相机间的位姿变换。   需要注意的事&#xff0c;EPNP可以同时使用N组路标点构建M矩阵…

iOS开发UI篇—多控制器和导航控制器简单介绍

iOS开发UI篇—多控制器和导航控制器简单介绍 一、多控制器 一个iOS的app很少只由一个控制器组成,除非这个app极其简单。当app中有多个控制器的时候,我们就需要对这些控制器进行管理 有多个view时&#xff0c;可以用一个大的view去管理1个或者多个小view&#xff0c;控制器也是如…

值传递 和 地址传递 的区别(好多句话才可以说清)

要知道什么是**值传递**和**地址传递**&#xff0c;首先要知道什么是**基本数据类型**和**引用类型**。 Java的基本数据类型就八种&#xff08;除了这八种之外都是引用类型&#xff09;&#xff1a;◆整型&#xff1a;byte(8位) short(16位) int(32位) long(64位)&#xff1…

日期类的时间从为什么是从1970年1月1日(格林威治时间)

I suspect that Java was born and raised on a UNIX system.UNIX considers the epoch (when did time begin) to be midnight, January 1, 1970.是说java起源于UNIX系统&#xff0c;而UNIX认为1970年1月1日0点是时间纪元. 但这依然没很好的解释"为什么",出于好奇&a…

MySQL从5.7.32升级到8.0.22

目录 一、备份与导出数据 二、升级到MySQL-8.0.22同时解决字符集问题 2.1、卸载MySQL-5.7.32 2.2、安装MySQL-8.0.22 2.3、修改配置文件 my.cnf 三、导入数据及配置 3.1、重新创建数据库wordpress 3.2、导入表结构和数据 3.3、启动httpd 今天&#xff0c;贫僧的个人博客…

50个顶级开源营销应用程序

显然&#xff0c;开源营销应用程序占有一席之地。如今&#xff0c;营销部门负责相当大比例的企业应用程序购买和部署决策。事实上&#xff0c;Gartner预测&#xff0c;到2017年&#xff0c;首席营销官&#xff08;CMO&#xff09;将比首席信息官&#xff08;CIO&#xff09;在I…