搞了这么多年的技术,一直对 事件与命令、函数与方法的概念模糊不清。今天详细记录一下。
函数与方法
第一门语言学习的c语言,老师常说写一个函数或者库函数。
其实编程和数学密不可分,以数学为基础的一门科学。
数学里常见的函数 y = sin(x). 这是个sin叫函数,不是叫方法。
学c语言,写一个函数,调用一个方法。
函数白话文的解释就是一堆指令(某个步骤,可以包括方法)封装成一个整体。
方法白话文的解释就是使用函数。
比如常说用什么方法解决某某问题。
解决某一类问题可以分装成一个函数,如果向解决这个问题,直接调用这个函数就行。 调用这个函数也即使用这个方法。
总结:
在函数式编程的语言中 没必要太过纠结这两个概念。可以理解为就是一个意思。
比如c语言,lua, javascript 等等语言中没有对象的概念,
在面向对象的语言中, 方法一般是指对象的行为。
比如经常有人问 某某类有哪些方法。 而不会问这个类有些函数。
函数强调功能定义,方法强调功能的使用。 当然函数中可以包括方法调用。
事件与命令与信号
理论:
事件是可以被控件识别的操作。事件有系统事件和用户事件
命令形容在对计算机程序编程时所下达的编程指令。
信号是运载消息的工具,是消息的载体
白话文里的事件:
常见的事件有 点击事件,触摸事件等等, 这些都是由于用户点击按钮,之后生成的事件。
描述一个事件通常是
class event{
事件类型
事件发生时间
}
指的是某个事情发生了。后续产生什么影响,制作事件的人是不知道的。
如果点击了某个按钮,用户发了一个点击事件,但是这个事件之后,是关机电脑,还是退出游戏是不知道的。
正规的应用程序,一般在按钮上表明,该按钮事件之后的用途, 比如显示一个QQ图标,或者QQ登陆,用户点击一下,就登陆了。
非正规的应用程序,点击QQ按钮,可能后台执行一个病毒。
总的来说,事件之后产生什么影响或者说做什么事情,由应用程序制作者定义。 事件之后没有任何反应也是很有可能的,
现在很多APP,都有出现级个别按钮点击后无反应的情况。可能有bug也可能是开发人员太忙没时间处理。
如果是给用户用的,为了提高用户体验我觉得还是给一个用户可以感知到的信息(弹窗或者刷新刷新数据之类的)为好。
白话文里的命令:
常见的命令 ls, prep, find top 等等命令。 这些命令Linux操作系统提供。由操作系统执行。其实这些都是可执行程序。叫主命令,标识应用程序本身
还有一种叫子命令,标识具体动作。 这个动作可以是打印一句话,也可以播放一段视频,或者调用其他打开其他应用,当然也可以啥都不做, 这个取决于应用设计本身。
一个通常会有一个help命令,或者有一个说明文档,来告诉别人应用系统里有哪些命令,已经如何使用。
在一个比较大软件项目里,也经常会设计一个这个命令系统。
比如svn软件。 提供的命令有 ls 、add 、 rm 、help等等
描述一个命令通常是
class commad{
命令名
}
只有应用软件才能认识
在函数式编程里,命令模式通常是这样的
switch(cmdName):{
case "rm": 做相应删除事情
case "add": 做相应添加事情
....
}
在面对对象编程里,命令模式通常是这样的
class Command{
Cammad()
excute() = 0 // 抽象方法
}
class RmCommand 继承 Command{
excute() {执行删除的操作}
}
class AddCommand 继承 Command{
excute() {执行添加的操作}
}
switch(cmdName):{
case "rm": rm.excute()
case "add": add.excutue()
....
}
区别
命令 主动性很强, 制作命令的人很清楚,要做什么。 【即将发生】
事件 被动性很强。 生产事件的人不知道,接下来发生什么。【已经发生】
相同点:
事件之后或者命令之后都是要做一些事情(当然也可以啥都不做)。
事件有事件队列,事件不能撤销,因为已经发生了。
命令有命令流, 命令可以撤销。比如文本编辑器,可以撤销更改
实际应用中的例子:
游戏中,接入了微信SDK, 点击登陆,弹起了微信, 让用户授权, 用户有2种操作, 取消授权, 授权并登陆。
无论用户选择点击哪一个按钮, 都会通知到游戏应用中。 对微信来说 这个很明显就是事件,他不知道游戏接下来要做什么处理。
对游戏来说,如果用户点击了授权并登陆,他会得到一个code码,把这个code码保存即可。
=====================================
信号:
说白了就是一个数据而已。
比如系统信号, kill -9 进程ID。 强制杀死某个进程。 这个杀死进程的时候,系统会先给这个进程发一个终止数据,然后在杀死。
应用程序收到信号会可以做保存数据的动作,或者其他动作。
也就是说执行某个动作前,先告知一下,然后在执行。有先兆性。
如果信号产生了,表示之后动作一定会执行。如果某某程序崩溃,系统会给这个程序发送崩溃信号,然后在关掉应用程序。
应用程序可以保存堆栈信息,以供分析什么原因导致的崩溃。
操作系统是发送者, 应用程序是接收者。
软件架构里,有一个消息的概念, 其实和信号差不多,但是也有不同点。
发送消息可以任何时候任何代码段都可以发送。 接收者可以是任何类或者其他系统(服务器或者其他应用进程)。
如程序启动时发送一个消息。 结束运行发送消息。
发送消息的时候说明动作正在执行, 仅仅是做一个通知而已。 这个通知可以是命令,可以是事件,也可以其他数据。
消息的概念比信号的概念更广, 网络消息,内部消息, 层与层之间的消息,事件消息, 命令消息等等这些统称为消息。
有发送者一般就有接收者,不然发消息毫无意义。
函数调用其实也是一种发送消息的一种体现,具体函数肯定是接收者, 发送者可以发生任何地方。 这个接收者是唯一的。这种耦合太紧了。
一般的软件架构里,发送者不知道接收者是谁,接收者也不知道发送者时,两者解偶是有很多好处的。
实现这样的模式有 观察者模式,命令模式,消费者/生产者模型, 消息队列(queue,redis,rabbitmq等),中介模式,都可以实现两者解偶。
这些模式都有一个通用点就是有一个存储消息的容器。只不过职责不一样而已。搞设计不要太执迷于设计模式。
最简单的lua 实现就是下面这样。
local data = {}
function send(msg) table.insert(data,msg) end
function recv() dispatch(table.remove(data,1)) end