文章目录
一、通过委托执行多个函数
假设我们在某个场景下需要运行一个逻辑:
关闭破真空-关闭吸真空-打开吸真空-延时200ms-处理其他逻辑-关闭吸真空-打开破真空-延时200ms-关闭破真空
其中每一个的执行都有可能是失败的(比如真空表值异常、通讯失败等原因),失败后就要报警等待人工检查处理而不应该继续往下执行
【以下代码比较长,但都是最简单的模型示例而已,请耐心看完】
我们常规的做法一般是这样:
public bool Run()
{
bool flag = false;
flag = CloseBreakVacuum();
if (!flag)
{
return false;
}
flag = CloseSuctionVacuum();
if (!flag)
{
return false;
}
flag = OpenSuctionVacuum();
if (!flag)
{
return false;
}
Delay(200);
OtherLogic();
flag = CloseSuctionVacuum();
if (!flag)
{
return false;
}
flag = OpenBreakVacuum();
if (!flag)
{
return false;
}
Delay(200);
flag = CloseBreakVacuum();
if (!flag)
{
return false;
}
return flag;
}
public bool CloseBreakVacuum()
{
// TODO..关闭破真空,读真空表气压值判断是否关闭成功
return true;
}
public bool CloseSuctionVacuum()
{
// TODO..关闭吸真空,读真空表气压值判断是否关闭成功
return true;
}
public bool OpenBreakVacuum()
{
// TODO..打开破真空,释放产品时防止产品黏在吸嘴上,读真空表气压值判断是否成功释放到产品
return true;
}
public bool OpenSuctionVacuum()
{
// TODO..打开吸真空,吸取产品,读真空表气压值判断是否成功吸取到产品
return true;
}
public void Delay(int ms)
{
// TODO..延时指定时间
}
public void OtherLogic()
{
// TODO..处理其他逻辑
}
可以看出来这样的可读性太差了,那么如何优化呢?我们可以使用委托的做法:
public bool Run()
{
bool flag = false;
foreach (var func in new Func<bool>[] { CloseBreakVacuum, CloseSuctionVacuum, OpenSuctionVacuum })
{
flag = func();
if(!flag)
{
return false;
}
}
Delay(200);
OtherLogic();
foreach (var func in new Func<bool>[] { CloseSuctionVacuum, OpenBreakVacuum })
{
flag = func();
if (!flag)
{
return false;
}
}
Delay(200);
foreach (var func in new Func<bool>[] { CloseBreakVacuum })
{
flag = func();
if (!flag)
{
return false;
}
}
return true;
}
public bool CloseBreakVacuum()
{
// TODO..关闭破真空,读真空表气压值判断是否关闭成功
return true;
}
public bool CloseSuctionVacuum()
{
// TODO..关闭吸真空,读真空表气压值判断是否关闭成功
return true;
}
public bool OpenBreakVacuum()
{
// TODO..打开破真空,释放产品时防止产品黏在吸嘴上,读真空表气压值判断是否成功释放到产品
return true;
}
public bool OpenSuctionVacuum()
{
// TODO..打开吸真空,吸取产品,读真空表气压值判断是否成功吸取到产品
return true;
}
public void Delay(int ms)
{
// TODO..延时指定时间
}
public bool OtherLogic()
{
// TODO..处理其他逻辑
return true;
}
这样看,很明显,结构化的代码可读性是不是更加强了
但好处还不止这个,我们再发散下思维,每一步都可能错误,假设是通讯丢包出错,那我们再执行一次是不是就可能成功了?好了,现在欠收拾的产品经理新增了需求,每一步如果重复失败三次(次数需要可以修改)才认为是失败。
那原来的代码可能是这样处理的:
int retryTimes = 3; //重试次数
int errorCount = 0; //失败次数
public bool Run()
{
bool flag = false;
errorCount = 0;
while (errorCount < retryTimes && !flag)
{
flag = CloseBreakVacuum();
errorCount++;
}
if (!flag)
{
return false;
}
errorCount = 0;
while (errorCount < retryTimes && !flag)
{
flag = CloseSuctionVacuum();
errorCount++;
}
if (!flag)
{
return false;
}
errorCount = 0;
while (errorCount < retryTimes && !flag)
{
flag = OpenSuctionVacuum();
errorCount++;
}
if (!flag)
{
return false;
}
Delay(200);
OtherLogic();
errorCount = 0;
while (errorCount < retryTimes && !flag)
{
flag = CloseSuctionVacuum();
errorCount++;
}
if (!flag)
{
return false;
}
while (errorCount < retryTimes && !flag)
{
flag = OpenBreakVacuum();
errorCount++;
}
if (!flag)
{
return false;
}
Delay(200);
while (errorCount < retryTimes && !flag)
{
flag = CloseBreakVacuum();
errorCount++;
}
if (!flag)
{
return false;
}
return true;
}
public bool CloseBreakVacuum()
{
// TODO..关闭破真空,读真空表气压值判断是否关闭成功
return true;
}
public bool CloseSuctionVacuum()
{
// TODO..关闭吸真空,读真空表气压值判断是否关闭成功
return true;
}
public bool OpenBreakVacuum()
{
// TODO..打开破真空,释放产品时防止产品黏在吸嘴上,读真空表气压值判断是否成功释放到产品
return true;
}
public bool OpenSuctionVacuum()
{
// TODO..打开吸真空,吸取产品,读真空表气压值判断是否成功吸取到产品
return true;
}
public void Delay(int ms)
{
// TODO..延时指定时间
}
public void OtherLogic()
{
// TODO..处理其他逻辑
}
而使用委托后可以这样处理:
int retryTimes = 3; //重试次数
public bool Run()
{
bool flag = false;
foreach (var func in new Func<bool>[] { CloseBreakVacuum, CloseSuctionVacuum, OpenSuctionVacuum })
{
flag = RetryFunc(func, retryTimes);
if(!flag)
{
return false;
}
}
Delay(200);
OtherLogic();
foreach (var func in new Func<bool>[] { CloseSuctionVacuum, OpenBreakVacuum })
{
flag = RetryFunc(func, retryTimes);
if (!flag)
{
return false;
}
}
Delay(200);
foreach (var func in new Func<bool>[] { CloseBreakVacuum })
{
flag = RetryFunc(func, retryTimes);
if (!flag)
{
return false;
}
}
return true;
}
protected bool RetryFunc(Func<bool> func, int retryTimes = 3)
{
bool flag = false;
int errorCount = 0;
while (errorCount < retryTimes && !flag)
{
flag = func();
errorCount++;
}
return flag;
}
public bool CloseBreakVacuum()
{
// TODO..关闭破真空,读真空表气压值判断是否关闭成功
return true;
}
public bool CloseSuctionVacuum()
{
// TODO..关闭吸真空,读真空表气压值判断是否关闭成功
return true;
}
public bool OpenBreakVacuum()
{
// TODO..打开破真空,释放产品时防止产品黏在吸嘴上,读真空表气压值判断是否成功释放到产品
return true;
}
public bool OpenSuctionVacuum()
{
// TODO..打开吸真空,吸取产品,读真空表气压值判断是否成功吸取到产品
return true;
}
public void Delay(int ms)
{
// TODO..延时指定时间
}
public bool OtherLogic()
{
// TODO..处理其他逻辑
return true;
}
好了,本文章就到这里了,具体区别,需要自己细细体悟,具体用法,需要举一反三