博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
责任链模式的具体应用 ServiceStack.Redis订阅发布服务的调用
阅读量:6908 次
发布时间:2019-06-27

本文共 6010 字,大约阅读时间需要 20 分钟。

 

1.业务场景

    生产车间中使用的条码扫描,往往一把扫描枪需要扫描不同的条码来处理不同的业务逻辑,比如,扫描投入料工位条码、扫描投入料条码、扫描产出工装条码等,每种类型的条码位数是不一样,因此通过条码长度来进行业务区分。

2.初步设计

    面对此场景,能够想到的最简单的设计就是使用if...else if...或者swith进行判断,因此,我们编写的代码如下

1 switch(barCode.length) 2 { 3     case 3: 4         DoSomething1(); 5         break; 6     case 4: 7         DoSomething2(); 8         break; 9     case 5:10         DoSomething3();11         break;12     default:13         DoSomething4();14         break;15 }

 

    使用是if...else if...或者switch已经基本上满足了需求,以后需要添加扫描场景,只需要增加判断,完成对应的方法即可。

    作为一个程序员,仅仅满足需求的话,往往降低了对自己的要求,同时,随着扫描业务的增加,switch中的代码逐渐增加,多到我们自己都觉得这段代码读起来就像是吃着前天剩下的硬馒头一样,难以下咽。

3.设计提升

上述场景完全可以使用设计模式中的责任链模式来进行优化,实施步骤如下:

3.1 定义处理结果

      一个处理在责任链上流动时,有两种结果,一是不能处理,转给其后继者,二是可以处理,同时又引出两种结果,处理成功和处理失败。因此,对处理结果统一定义为枚举类型

1 public enum HandleResult 2 { 3   ///  4    /// 成功 5    ///  6    Success=0, 7    ///  8    /// 失败 9    /// 10    Failed = 1,11    /// 12    /// 未处理13    /// 14    Unhandle = 215 }

 

3.2定义业务抽象类AbstractBarCodeHandler

    定义业务抽象类,包含一个属性“Successor”,用于标记其后继者,一个公共方法“HandleRequest”,当调用真正的业务处理方法时返回未处理,则调用其后继者进行处理,一个抽象方法“HandleRequestCore”,每个扫描业务具体类,需要实现此方法,并对条码进行处理。

1     public abstract class AbstractBarCodeHandler 2     { 3         ///  4         /// 责任处理的后继者 5         ///  6         private AbstractBarCodeHandler mSuccessor; 7  8         ///  9         /// 责任处理的后继者10         /// 11         public AbstractBarCodeHandler Successor12         {13             get14             {15                 return mSuccessor;16             }17 18             set19             {20                 mSuccessor = value;21             }22         }23 24         /// 25         /// 请求处理方法26         /// 27         public HandleResult HandleRequest(string barCode)28         {29             var result = HandleRequestCore(barCode);30             if (result == HandleResult.Unhandle)31             {32                 if (Successor != null)33                 {34                     Successor.HandleRequest(barCode);35                 }36                 else37                 {38                     Console.WriteLine($"The BarCode:{barCode} do not handle.");39                 }40             }41             return result;42         }43 44         protected abstract HandleResult HandleRequestCore(string barCode);45     }

 

 

3.3定义业务实现具体类

     每个具体的条码扫描业务,都定义一个类,继承自AbstractBarCodeHandler,并实现其抽象方法,比如,

  LocationBarCodeHandler:工位条码处理类

  LocationInBarCodeHandler:入库条码处理类
  LocationOutBarCodeHandler:出库条码处理类
  MaterialBarCodeHandler:物料条码处理类
  ToolingBarCodeHandler:工装条码处理类

3.4 生成责任链

    依次对每个类进行初始化,并设置其后继者,比如:

  工位条码处理类实例.Successor=入库条码处理类实例;

  入库条码处理类实例.Successor=出库条码处理类实例;
  出库条码处理类实例.Successor=物料条码处理类实例;
  物料条码处理类实例.Successor=工装条码处理类实例;

3.5处理过程

     当条码枪扫描一个条码,便发起了一个处理请求,该请求在责任链上依次流动(工位->入库->出库->物料->工装),若某个节点不能够处理,则需要交接去后继者,若能够处理,则返回处理结果,当所有的节点都无法处理,需要给出对应的提示。

 

 

 

----

 

 

 

 

1.Redis订阅发布介绍

Redis订阅发布是一种消息通信模式:发布者(publisher)发送消息,订阅者(Subscriber)接受消息。类似于设计模式中的观察者模式。
发布者和订阅者之间使用频道进行通信,当需要发送消息时,发布者通过publish命令将消息发送到频道上,该消息就会发送给订阅这个频道的订阅者。

2.ServiceStack.Redis

  ServiceStack.Redis是Redis的C#版本的客户端,是ServiceStack的一部分。
    ServiceStack的地址为

 

3.订阅者

首先创建RedisClient,然后调用CreateSubscription()方法创建订阅客户端,然后设置订阅客户端的几个事件:
OnMessage:接受到消息时。
OnSubscribe:订阅频道时。
OnUnSubscribe:取消订阅频道时。
最后,调用subscribeToChannels(channelName),订阅频道。
详细代码如下:

1 ///  2     /// Redis订阅 3     ///  4     public static void Subscribe() 5     { 6         using (RedisClient consumer = new RedisClient("127.0.0.1", 6379)) 7         { 8             //创建订阅 9             IRedisSubscription subscription = consumer.CreateSubscription();10             //接受到消息时11             subscription.OnMessage = (channel, msg) =>12             {13                 Console.WriteLine($"从频道:{channel}上接受到消息:{msg},时间:{DateTime.Now.ToString("yyyyMMdd HH:mm:ss")}");14                 Console.WriteLine($"频道订阅数目:{subscription.SubscriptionCount}");15                 Console.WriteLine("___________________________________________________________________");16             };17             //订阅频道时18             subscription.OnSubscribe = (channel) =>19             {20                 Console.WriteLine("订阅客户端:开始订阅" + channel);21             };22             //取消订阅频道时23             subscription.OnUnSubscribe = (a) => { Console.WriteLine("订阅客户端:取消订阅"); };24 25             //订阅频道26             subscription.SubscribeToChannels("channel1");27         }28     }

4.发布者

首先创建RedisClient,然后调用PublishMessage(channelName,message)发布消息。
详细代码如下:
RedisClient client = new RedisClient("127.0.0.1", 6379);
string message = "发布消息测试";
client.PublishMessage("channel1", message);

到目前为止,一个简单的Redis发布订阅就完成了。

5.Redis发布服务
使用发布者仅仅能够发布消息,但是不能够检测一些事件的变化,Redis中还有一个RedisPublishServer的类,里面包括一些事件能够使我们很好地检测服务的运行。
OnMessage:接受到消息;
OnStart:发布服务开始运行时;
OnStop:发布服务停止运行时;
OnUnSubscribe:订阅者取消订阅时;
OnError:发布出现错误时;
OnFailover:Redis服务器冗余切换时;
发布服务端初始化完成后,调用Start()方法,开始执行发布服务。
发布服务执行后,执行消息的发布client.PublishMessage时,发布服务端也能够接受到发布的消息。
详细代码如下:

1 public void Publish() 2     { 3         //PooledRedisClientManager 4         IRedisClientsManager redisClientManager = new PooledRedisClientManager("127.0.0.1:6379"); 5         //发布、订阅服务 IRedisPubSubServer 6         RedisPubSubServer pubSubServer = new RedisPubSubServer(redisClientManager, "channel1") 7         { 8             OnMessage = (channel, msg) => 9             {10                 Console.WriteLine($"从频道:{channel}上接受到消息:{msg},时间:{DateTime.Now.ToString("yyyyMMdd HH:mm:ss")}");11                 Console.WriteLine("___________________________________________________________________");12             },13             OnStart = () =>14             {15                 Console.WriteLine("发布服务已启动");16                 Console.WriteLine("___________________________________________________________________");17             },18             OnStop = () => { Console.WriteLine("发布服务停止"); },19             OnUnSubscribe = channel => { Console.WriteLine(channel); },20             OnError = e => { Console.WriteLine(e.Message); },21             OnFailover = s => { Console.WriteLine(s); },22         };23         //接收消息24         pubSubServer.Start();25     }

 

每天进步一点点...
 
分类: 
标签: 

 

 

转载地址:http://eyfcl.baihongyu.com/

你可能感兴趣的文章
用python画微信捂脸_用 Python 画一个捂脸表情
查看>>
mysql alter float_mysql-数据类型
查看>>
服务器被黑 追寻ip_服务器被如下ip攻击,如何根据ip超找攻击来源
查看>>
java 方差_java计算方差、标准差(均方差)实例代码
查看>>
<<java程序设计>>_Java程序设计
查看>>
java import lang_java.lang
查看>>
java实验Java面向对象编程_Java实验项目 面向对象编程.doc
查看>>
java ldap添加用户名密码_使用用户名和密码的Java LDAP身份验证
查看>>
java 单精度数据后缀_java有哪些基本数据类型
查看>>
java 死锁 定位_Java中死锁的定位与修复
查看>>
mysql数据库内存结构_mysql 内存结构
查看>>
java xml集合标签_java使用demo4j实现对指定目录下的XML文件指定标签下的内容进行编辑...
查看>>
检查表单行为的JAVA代码_form 表单验证
查看>>
JAVA怎么使用escape_Java中的escape,unescape方法
查看>>
zabbix Queue队列
查看>>
my-innodb-heavy-4G.cnf配置文件注解
查看>>
对IT人员如何提升自身英语能力的几点建议
查看>>
360败诉:从先例到下一例
查看>>
thinkphp学习笔记1—目录结构和命名规则
查看>>
C# 动态调用WebService
查看>>