温湿度监控报警程序,设计模式 求指点。

hfdsoft 2012-05-27 06:12:26
1、程序入口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace TemperatureAlarm
{
internal class Program
{
private static void Main(string[] args)
{
IList<Detectors> detectorList = new List<Detectors>();

using (var db = new LGJKEntities())
{
var query = from p in db.Detectors
select p;
detectorList = query.ToList();
foreach (var item in detectorList)
{
Detector d = new Detector(item.ID);
d.DataChange += (new AlarmCenter()).Alarm;
d.DoMonitor();
Console.WriteLine(string.Format("Monitor Start by {0}",item.ID));
}
}
Console.ReadLine();
}
}
}


2、探头对象,拥有DataChange事件,主要负责监控探头当前各项参数
Detector.cs

public class Detector
{
private int _detectorID = 0;
#region 构造函数
public Detector()
{

}
/// <summary>
/// 传入探头ID
/// </summary>
/// <param name="detectorID"></param>
public Detector(int detectorID)
{
this._detectorID = detectorID;
}
#endregion



#region 事件与委托定义


public Action<Object, MonitorEventArgs> DataChange;
/// <summary>
/// MonitorEventArgs类,用于传递参数
/// </summary>
public class MonitorEventArgs : EventArgs
{
public Detectors info;
public MonitorEventArgs(Detectors d)
{
this.info = d;
}
}
#endregion

#region 自定义事件

/// <summary>
/// 数据更新
/// </summary>
/// <param name="e"></param>
protected virtual void OnDataChange(MonitorEventArgs e)
{
if (DataChange != null)
{
DataChange(this, e);
}
}
#endregion

#region 公共方法
public void DoMonitor()
{
if (_detectorID > 0)
{
//开始任务
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 6000;
timer.Enabled = true;
timer.Elapsed += new ElapsedEventHandler(GetDetectorInfoByID);
timer.Start();
}
else
{
Exception ex = new Exception("探头ID不正确");
ExceptionSave.Save("Detector.DoMonitor." + _detectorID.ToString(), ex);
}

}
#endregion

#region 私有方法
/// <summary>
/// 获取温湿度信息
/// </summary>
private void GetDetectorInfoByID(object source, ElapsedEventArgs e)
{
try
{
Detectors d = new Detectors();
using (var db = new LGJKEntities())
{
d = db.Detectors.First(p => p.ID == _detectorID);
}
MonitorEventArgs ev = new MonitorEventArgs(d);
OnDataChange(ev);
}
catch (Exception ex)
{
ExceptionSave.Save("Detector.GetDetectorInfoByID." + _detectorID.ToString(), ex);
}
}
#endregion
}

3、报警中心,在DataChange事件触发时,交由此类中的Alarm进行处理,负责判断当前传入的探头参数是否应该触发警报,并根据警报开关进行选择性报警。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TemperatureAlarm
{
public class AlarmCenter
{
public void Alarm(Object sender, Detector.MonitorEventArgs e)
{
Detectors d = e.info;
//总开关
if (d.AlarmSP == "关")
{
return;
}
TAlarm(d);
HAlarm(d);
}

/// <summary>
/// 湿度报警判断
/// </summary>
/// <param name="d"></param>
private void HAlarm(Detectors d)
{
AlarmInfo alarmInfo = new AlarmInfo(Common.FormatDouble(d.Humidity), Common.FormatDouble(d.MinHumidity),
Common.FormatDouble(d.MaxHumidity), d.HumidityAlarm, d.HumidityCondition);
if (alarmInfo.IsAlarm)
{
//短信报警
if (d.SMSAlarm == "开")
{
SMSAlarm sms = new SMSAlarm();
sms.DoAlarm();
}
//设备报警
if (d.DeviceAlarm == "开")
{
DeviceAlarm device = new DeviceAlarm();
device.DoAlarm();
}
//服务器报警
if (d.ServerAlarm == "开")
{
ServerAlarm server = new ServerAlarm();
server.DoAlarm();
}
}
}
/// <summary>
/// 温度报警判断
/// </summary>
/// <param name="d"></param>
private void TAlarm(Detectors d)
{
AlarmInfo alarmInfo = new AlarmInfo(Common.FormatDouble(d.Temperature), Common.FormatDouble(d.MinTemperature),
Common.FormatDouble(d.MaxTemperature), d.TemperatureAlarm, d.TemperatureCondition);
if (alarmInfo.IsAlarm)
{
//短信报警
if (d.SMSAlarm == "开")
{
SMSAlarm sms = new SMSAlarm();
sms.DoAlarm();
}
//设备报警
if (d.DeviceAlarm == "开")
{
DeviceAlarm device = new DeviceAlarm();
device.DoAlarm();
}
//服务器报警
if (d.ServerAlarm == "开")
{
ServerAlarm server = new ServerAlarm();
server.DoAlarm();
}
}
}
}

/// <summary>
/// 短信报警
/// </summary>
public class SMSAlarm
{
public void DoAlarm()
{

}
}
/// <summary>
/// 设备上的警号报警
/// </summary>
public class DeviceAlarm
{
public void DoAlarm()
{

}
}
/// <summary>
/// 服务器上的警号报警
/// </summary>
public class ServerAlarm
{
public void DoAlarm()
{

}
}
}


4、报警信息,判断报警信息是否达到报警条件

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TemperatureAlarm
{
/// <summary>
/// 警报类:负责判断传入的参数是否触发警报
/// </summary>
public class AlarmInfo
{
public double MaxValue;
public double MinValue;
public double Value;
public string AlarmSwitch;
public string AlarmCondition;
public int AlarmCode;
public bool IsAlarm;
public AlarmInfo()
{

}
public AlarmInfo(double _val, double _min, double _max, string _switch, string _condition)
{
this.MaxValue = _max;
this.MinValue = _min;
this.Value = _val;
this.AlarmSwitch = _switch;
this.AlarmCondition = _condition;
this.AlarmCode = GetAlarmCode();
this.IsAlarm = CheckAlarm();

}
/// <summary>
/// 判断是否需要报警
/// </summary>
/// <param name="alarmInfo"></param>
/// <returns></returns>
private bool CheckAlarm()
{
int iConditionValue = 0;
if (this.AlarmSwitch == "开")
{
switch (this.AlarmCondition)
{
case "上下都报":
iConditionValue = 3;
break;
case "上报":
iConditionValue = 2;
break;
case "下报":
iConditionValue = 1;
break;
case "不报":
iConditionValue = 0;
break;
default:
iConditionValue = 3;
break;
}
}
return ((this.AlarmCode & iConditionValue) > 0);
}
/// <summary>
/// 计算报警代码:11,10,01
/// 分别代表:上下都报,上报,下报
/// </summary>
/// <returns></returns>
private int GetAlarmCode()
{
int intAlarmCode = 0;
intAlarmCode += CalcValue(this.Value, this.MaxValue, 2);
intAlarmCode += CalcValue(this.MinValue, this.Value, 1);
return intAlarmCode;
}
/// <summary>
/// 当前者大于后者时,返回累加值
/// </summary>
/// <param name="firstNum"></param>
/// <param name="secondNum"></param>
/// <param name="plusValue"></param>
/// <returns></returns>
private int CalcValue(double firstNum, double secondNum, int plusValue)
{
if (firstNum <= secondNum)
{
plusValue = 0;
}
return plusValue;
}
}
}


5、疑问,主要在报警器选择这个地方,觉得代码只是能完成任务,但不够优雅,无论是简单工厂模式、策略模式还是工厂方法模式都是多选一。。小弟初学设计模式,希望能得到前辈们的指点,谢谢。

如有其他不正之处也请一一指出,小弟感激不尽。。
...全文
292 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
hfdsoft 2013-05-23
  • 打赏
  • 举报
回复
引用 9 楼 yuandonghuia 的回复:
我去,又结贴了.靠
...我是来围观你的。
yuandonghuia 2012-06-04
  • 打赏
  • 举报
回复
我去,又结贴了.靠
yuandonghuia 2012-06-04
  • 打赏
  • 举报
回复
这玩意一句两句可说不清.据说java里面的观察者模式其实就是C#的委托,我Java没学过,不敢定论.
还有工厂模式不用反射里面用switch,我觉得没多大用.到时候每次改动,都要去改Switch.
或者不用反射的话也可以,我之前搞过一个,但是要求你对继承用的很好,先有个基类,再来个虚方法之类,工厂里面Switch的地方,调用这个基类的方法,然后不同的子类可以根据自己的特性来overwrite这个虚方法,这样至少能做到不改动Switch的地方.
hfdsoft 2012-05-28
  • 打赏
  • 举报
回复
可能是我问得太肤浅,太浮躁了。结贴吧。谢谢各位指点。
threenewbee 2012-05-27
  • 打赏
  • 举报
回复
因为你不会委托,所以才大量编写if或者switch分支,所以傻乎乎地在HAlarm和TAlarm中把相同的代码写了两次。工厂模式了半天,反射却不会用。唉。
足球中国 2012-05-27
  • 打赏
  • 举报
回复
楼主的代码问题很多。确定关闭的时候程序没有异常???
hfdsoft 2012-05-27
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]
这当然,设计模式本身也没有“让代码优雅”的功能。你要把代码写优雅,就要先把C#语言学好。
[/Quote]

一个人在实践中摸索走得很难,求前辈点拨。。
hfdsoft 2012-05-27
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
这个典型的用观察者来做吧?
[/Quote]

之前看例程的时候说这就是观察者模式,后来看书上的观察者模式好像又不一样。

现在迷茫的是后续处理问题。
threenewbee 2012-05-27
  • 打赏
  • 举报
回复
这当然,设计模式本身也没有“让代码优雅”的功能。你要把代码写优雅,就要先把C#语言学好。
Conmajia 2012-05-27
  • 打赏
  • 举报
回复
这个典型的用观察者来做吧?

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧