关于"短信处理"模式的一段讨论

DH

请教下大家一个设计模式的问题

业务:
有多种短信指令,系统会根据接收到的指令进行相应的业务处理,处理完成后,系统会回复一条短信

这种业务处理,可以用哪个设计模式来做?

QX

状态模式

DH

小雪,短信指令可能会增加,也可能会减少

QB

命令模式

DH

用命令模式更合适?

QB

命令模式看起来挺奇怪的。

QB

interface ICommand{
ICommandResult Execute();
}

abstract class CommandResult{
virtual ToString();
}

DH

如何理解

QB

public class Invoker
{
void Invoke(ICommand cmd)
{
CommandResult ret = cmd.Execute();
MessageSender.Send(ret)
}
}

我觉得 如果是同步模式话 用这种方式就可以了。不好说是什么设计模式。

interface ICommand{
CommandResult Execute();
}

敲错了,qq敲代码蛋疼。

DH

我再说下业务, 系统接收到上行短信后,会把短信push入消息队列,
有一个线程在监听消息队列,每pop出一条消息,都会判断这条消息是什么指令,不同指令处理不同业务

QB

可以用个工厂模式来创建消息。HandlerFactory,webserver里面基本上是这样处理的。

.aspx .ashx .asmx 不同的扩展名通过HttpHandlerFactory 创建不同的Handler

DH

消息类型的判断是放在工厂里做还是放在监听消息队列的线程来做?

QB

Factory里面来做

if(aspx)
return aspxHandler;
else if
....

STST


这种方式,如果分支的数量本身就不稳定,那么维护起来不方便

QB

如果性能要求不高的话 可以用反射。

但是如果要求性能的话也只是修改一个类。可以接受。

DH

指令一般都是固定那些

应该不会怎么变

STST

尽量避免修改一个类

QB

这个还是看项目取舍吧。用反射来处理可以做到只修改配置文件。

DH

目前有11个指令类型,在想着怎么优雅的不需要写分支

STST

具体到这个例子,应该是工厂加职责链处理起来比较合适,个人认为

QB

用map
HandlerMap(string cmdString, Type handlerType)

QB

如果对多线程比较擅长,handler 做成单例的也可以。

QB

但是我觉得11个指令 你就if else 简单有效。性能也无可挑剔

DH

STST
为什么会想到职责链的?

STST

18:47:35

这里的每个职责就是每个相应的业务处理

然后就只要把这些职责串起来,最好把业务量最多的职责放前面

QB

如果需要对命令进行一些过滤操作的话 可以考虑责任链。如果只是单纯处理就不需要了。还是看业务需要。

STST

然后用一个工厂,负责创建职责链

这样处理满足了OCP原则

如果以后增加了业务处理,那么我们需要增加一个 职责
然后增加一个新的Factory20150405,负责创建新的职责链

不用去修改现有的类

QB

也是要改代码的

STST

这只是我的看法,不用改代码阿,只增加代码

QB

你新增了一个Factory 应该在程序里面去调用他啊

STST

使用那个Factory可以在配制文件里处理了

IOC的核心就是这个

选择哪个具体的工厂,可以放配置文件里处理的

这里也同时满足了DIP原则,底层依赖了高层

高层不依赖底层

QB

那你相当于要弄一个抽象工厂,我觉得不需要。简单工厂就可以了。抽象工厂的话要多不少类哦

STST

可以这么理解吧

@大模式-广州 ,这图画出来理解了吗?

DH

谢谢各位

我先看下

STST

针对一条短信X

不再关心是什么命令,直接丢给职责链表来处理

职责链表.Do(X)

每个职责里的处理方法象下面这样
Do(X)
{
if(需要自己处理(X)){具体处理;......}
else
Next.Do(X);
}

QB


修改一下

STST

这样处理无法满足OCP原则

QB

如果用反射的话是可以的。

STST

来了新的短信类型必定要修改

QB

不需要,我先写几句伪代码

DH

英界尔,
你的图是用什么工具画的,感觉挺漂亮的

STST

VS

DH

VISIO?

STST

visual studio

DH

哦哦

STST

QB

public interface IHandler
{
void Handle();
}

public class ConcreteHandlerA : IHandler
{
public void Handle()
{
// handle commandA
}
}

public class ConcreteHandlerB : IHandler
{
public void Handle()
{
// handle commandB
}
}

public static class HandlerFactory
{
public static IHandler CreateHandler(string commandType)
{
switch (commandType)
{
case "A":
return new ConcreteHandlerA();
case "B":
return new ConcreteHandlerB();
default:
throw new NotSupportedException();
}
}
}

public class CommandParser
{
public void Receive(string msg)
{
Command cmd = this.ParseCommand(msg);

IHandler handler = HandlerFactory.CreateHandler(cmd.CommandType);
handler.Handle();
}
}

STST


问题就在这里,来了C,D,E,F呢

QB

罩门在HandlerFactory 增加新的command 只需要修改HandlerFactory。

但是如果在HandlerFactory中用反射的话 就可以做到不修改代码。

性能与优雅的取舍。

要优雅就用反射。要性能就用switch case

你的方法也避免不了这个问题。

罩门是一样的

STST


这一过程,有反射的话如何写?

QB

责任链比较适合要对一个命令分别处理
比如HttpModule 或 Filter之类的。

假设配置文件中已经把 commandType与handlerType做好映射。

DH

像STST说的那种方案,可否通过Spring配置来避免后续修改代码问题

QB

string typeName = Configuration.GetTypeName(commandType);
Type handlerType = Type.GetType(typeName);
return (IHandler)Activator.CreateInstance(handlerType);

STST

@大模式-广州 那就是IOC

QB

是的。因为这种问题不用反射无解。必须要修改代码。

STST

看修改的是那里的代码,修改最顶层的代码代价很小,修改下面的代价较大

这里无论是哪种方案,都在努力做一件事情,将对"具体"的了解尽量网高层推

最理想的情况下,只有main函数需要知道所有的"具体"类

QB

哈哈 那就是标准的IOC了。

在Main里面做各种Mapping

DH

直接IOC是不是可以解决修改代码的问题,后续只要增加短信类型即可

QB

也是需要做映射的,但是一般IOC容器都支持配置文件,可以使用配置文件进行映射。

STST

@大钱币-北京 没错,肯定不止一种方式处理

DH

把所有短信类型IOC到一个list里,逐个循环,循环到匹配的类型跳出循环,否则next

STST

@大模式-广州 你这叫迭代,当然可以

DH

这样后面有新增的短信类型,只管新增类,往spring里配置

QB

IOC叫容器,他内部实现了这个循环匹配的过程。你要做的是把映射关系注册进去。要用的时候 直接resolve就可以了。

下班撤了。再见。

STST

如果你能自己控制循环过程的话,迭代当然可以

迭代和职责链的区别就是,谁来控制循环过程

X

没搞懂要迭代和职责链的目的是?

把获取具体的处理类抽象出来不行。?

STST

都是用来处理"循环"的

X

要加只要新加获取的处理类的抽象类的实现类。。

为什么会有循环?

一条短信会对应多条处理么?

STST

那么我问你,短信X对应哪个Handler的逻辑在那里?

DH

不是一条短信多个处理

而是有多种类型的短信

X

统一一个接收器。。根据接收到的短信类型,实例化具体的handler.

就这个场景的话没必要用链啊。。

STST

具体一个短信X,选择那个Handler Y,这个处理有两个地方可以处理

X

要是有一些别的场景,校验XXX之类 的到是有可能

STST

1,分支,if else
2,由每个业务处理类自身判断

X

如果只是处理短信这一个handler完全没必要用责任链了。

if else是用来干啥 的呢?

STST

干这个阿

X

这个方法可以抽象出来。。由子类去实现得了。

STST


那么我想了解的是,是否有一个职责链,处理一个请求的时候,会有多个职责去处理的情况吗?

X

就他这个场景。。我觉得没有。

STST

哦,那就是没有,采用什么模式,提前设计实际上并不可靠,要在实际中重构到模式才是可靠的

只要记住一点,要在实际演变中注意观察变化点,把变化点封装起来就可以了
面向对象:封装变化,抽象共同点

时间: 2024-10-13 11:28:49

关于"短信处理"模式的一段讨论的相关文章

【原创】起步互联网公司内部短信平台杂谈

前言 陆陆续续间间隔隔开发公司短信平台接口已经一段时间了,在年末的时候找个空闲把觉得实际可行的东西记录下来. 想了想,感觉这东西应该没啥好说的,但是又觉得哪里需要记一记,以后换个工作环境,还来一发呢,不就可以避免不必要的坑. 毕竟在实现短信接口的过程中,看似简单,但是有许多需要注意的地方和可以一步到位的地方可以记录下来,请大牛们分享探讨不足指正. 来吧,整理整理思绪. 开发背景 由于公司的APP端.微信公众号端.各种后台端和报警机制端等等的一系列应用和系统都需要用到一个基础功能:发短信.所以一开

[TPYBoard - Micropython] 五分种学会用TPYBoard - GPS 制作短信群发机

转载请注明:@小五义 http://www.cnblogs.com/xiaowuyi 欢迎加入讨论群 64770604 一.什么是TPYBoard-GPS TPYBoard-GPS又称TPYBoard V702,是目前市面上唯一支持通信定位功能的MicroPython开发板:支持Python3.0及以上版本直接运行.支持GPS+北斗双模定位.GPRS通信.短信功能.电话功能:板载温湿度.光敏.三轴加速度传感器.蜂鸣器.LCD5110显示屏.免费提供定位测试服务平台.实物如下图: 二.利用TPYB

Android软件开发之发送短信与系统短信库解析

今天我和同学们讨论一下Android平台下如何调用系统方法发送短信.接收短信.系统的短信库相关的问题.进入正题,我们先使用Eclipse工具模拟给自己的模拟器发送一条短信.在Eclipse下打开DDMS Incoming number: 这里须要填写的是发件人的手机号码,这里只能输入数字否则会无法发送. Message: 这里为发送的内容send: 上面两项都填写完毕点击发送键可以给模拟器发送短信. <ignore_js_op> 点击发送后,模拟器中就可以看到自己收到了一条消息 发件人的号码为

MicroPython+北斗+GPS+GPRS:TPYBoardv702短信功能使用说明

转载请以链接形式注明文章来源(MicroPythonQQ技术交流群:157816561,公众号:MicroPython玩家汇) TPYBoardv702是目前市面上唯一支持通信定位功能的MicroPython开发板:支持Python3.0及以上版本直接运行.支持GPS+北斗双模定位.GPRS通信.短信功能.电话功能:板载温湿度.光敏.三轴加速度传感器.蜂鸣器.LCD5110显示屏.免费提供定位测试服务平台. TPYBord_V7.0.2开发板上板载的通信器件是由深圳合方圆公司研发发的GU620通

短信拦截

Android系统在收到短信的时候会发送一条有序广播,我们如果定义一个接收者接收这个广播,就可以得到短信内容,也可以拦截短信. 定义广播接收者接收广播 android.provider.Telephony.SMS_RECEIVED  需要接收短信权限: <uses-permission android:name="android.permission.RECEIVE_SMS"/>  Android系统中收到短信的通知是一个有序广播,我们如需拦截垃圾短信,可以配置较高的Pri

PHP通过串口发短信

随技术进步,短信收发领域按时间先后产生了三种模式:BLOCK MODE,基于AT指令的TEXT MODE,基于AT指令的PDU MODE.其中,TEXT MODE比较简单,多款诺基亚手机均支持此款模式.西门子的手机大多数只支持PDU MODE.PDU 模式是收发短信的一种方法,短信正文经过十六进制编码后被传送.目前,PDU已取代BLOCK MODE. SMS是由Etsi所制定的一个规范(GSM 03.40 和GSM 03.38).当使用7-bits编码时,它可以发送最多160个字符;但用8-bi

【Android】几种常见广播监听器(Wifi,亮灭屏,Home键,短信)总结

Wifi状态监听的广播接收者 /** * 监控Wifi状态的广播接收器,注意不需要添加任何权限 */ public final class WifiStateReceiver extends BroadcastReceiver { private static final String TAG = "TagForWifiStateReceiver"; @Override public void onReceive(Context c, Intent intent) { Bundle b

短信相关的AT指令以及信令

本文链接:https://blog.csdn.net/sjz4860402/article/details/78552756 此次的短信AT指令和信令从以下几个方面介绍: 一 . 短信AT指令的格式二 . 短信AT指令的使用(超级终端)三 . 短信AT指令在log中的查看四 . 短信modem相关信令五 . 超级终端的使用(hyper_terminal)六 . 其他短信AT指令七 . CMC ERROR 错误码一 . 短信AT指令的格式 短信的编码方式有两种:text模式,pdu模式.因此短信的

SIM800L 发送短信和闪信

发送短信流程: 首先发送 AT 命令连接到模块, 然后发送 AT+CMGF=1 将短信模式设置为 text mode (模块默认是 pdu mode), 然后发送 AT+CMGS="+8610086",等待模块返回 '>' 字符,输入短信内容,最后发送 CTRL+Z (十六进制表示为 0X1A)完成短信的发送. AT\r\nOK AT+CMFG=1\r\nOK AT+CMGS="+8610086"\r\n>hello0x1a+CMGS: 13 发送闪信和