最近在做一个测试系统,就是读取功率计上的数据,在上位机软件上显示出来。
电脑界面不是我们这次的主讲就略过,我们这里主要讲一个类的实现。
最开始领导给了一个 远方的三相功率计 给我让我写上位机,很简单,我一会就实现出来了。
由于是三相功率计,所以我们先写个一相的基类出来
public class OnePhase { public float V { get; set; } public float A { get; set; } public float W { get; set; } public float VA { get; set; } public float PF { get; set; } }
远方的类
public class PF9830 { public PF9830() { P1 = new OnePhase(); P2 = new OnePhase(); P3 = new OnePhase(); P4 = new OnePhase(); } public OnePhase P1 { get; set; } public OnePhase P2 { get; set; } public OnePhase P3 { get; set; } public OnePhase P4 { get; set; } public void GetValues(byte[] data) { /* * 串口读取值的解释 * * P1.V = …… */ } }
实现类
class Test { public Test() { PowerMeter = new PF9830(); Port = new SerialPort(); Port.DataReceived += new SerialDataReceivedEventHandler(Port_DataReceived); } public PF9830 PowerMeter { get; set; } public SerialPort Port { get; set; } void Port_DataReceived(object sender, SerialDataReceivedEventArgs e) { int length = Port.BytesToRead; byte[] data = new byte[length]; Port.Read(data, 0, length); PowerMeter.GetValues(data); } }
工作很快就完成了,也正常运行。可是有一天,领导说远方的测试精度太差了,要换一个横河的功率计进行测试,最好有一个下拉列表,可以选择是哪个仪器。
我刚开始的时候直接再写一个横河的类出来,如下:
public class WT230 { public WT230() { P1 = new OnePhase(); P2 = new OnePhase(); P3 = new OnePhase(); P4 = new OnePhase(); } public OnePhase P1 { get; set; } public OnePhase P2 { get; set; } public OnePhase P3 { get; set; } public OnePhase P4 { get; set; } public void GetValues(byte[] data) { /* * 串口读取值的解释 * * P1.V = …… */ } }
class Test { public enum Powermeters { 远方, 横河 }; public Test() { PowerMeter1 = new PF9830(); PowerMeter2 = new WT230(); Port = new SerialPort(); Port.DataReceived += new SerialDataReceivedEventHandler(Port_DataReceived); } public PF9830 PowerMeter1 { get; set; } public WT230 PowerMeter2 { get; set; } public SerialPort Port { get; set; } private Powermeters flag; void Port_DataReceived(object sender, SerialDataReceivedEventArgs e) { int length = Port.BytesToRead; byte[] data = new byte[length]; Port.Read(data, 0, length); switch (flag) { case Powermeters.横河: PowerMeter2.GetValues(data); break; case Powermeters.远方: PowerMeter1.GetValues(data); break; default: break; } } }
这里我们会发现WT230与PF9830两个类中有很多相同的代码,只是GetValues()这个方法不现。
再的就是实现类的有两个实例PowerMeter1与PowerMeter2,这与UI交互方面会存在很大的问题。
这里我们如果运用抽象类就可以很容易的解决上面的两个问题
首先我们先抽象出一个 功率计 的类出来:
public abstract class PowerMeterBase { public PowerMeterBase() { P1 = new OnePhase(); P2 = new OnePhase(); P3 = new OnePhase(); P4 = new OnePhase(); } public OnePhase P1 { get; set; } public OnePhase P2 { get; set; } public OnePhase P3 { get; set; } public OnePhase P4 { get; set; } public abstract void GetValues(byte[] data);//抽象方法 }
然后实例远方与横河的类
public class PF9830:PowerMeterBase { public override void GetValues(byte[] data) { /* * 串口读取值的解释 * * P1.V = …… */ } }
public class WT230:PowerMeterBase { public override void GetValues(byte[] data) { /* * 串口读取值的解释 * * P1.V = …… */ } }
现在我们实现的UI交互类就简单多了
class Test { public enum Powermeters { 远方, 横河 }; public Test() { Port = new SerialPort(); Port.DataReceived += new SerialDataReceivedEventHandler(Port_DataReceived); } public PowerMeterBase PowerMeter { get; set; } //实现多态 public SerialPort Port { get; set; } private Powermeters flag; void Port_DataReceived(object sender, SerialDataReceivedEventArgs e) { int length = Port.BytesToRead; byte[] data = new byte[length]; Port.Read(data, 0, length); switch (flag) { case Powermeters.横河: PowerMeter = new WT230(); PowerMeter.GetValues(data); break; case Powermeters.远方: PowerMeter = new PF9830(); PowerMeter.GetValues(data); break; default: break; } } }
总结:
功率计(抽象类)WT230(实类)PF9830(实类)
对不同功率计的显示(多态)