通过委托执行多个函数


一、通过委托执行多个函数

假设我们在某个场景下需要运行一个逻辑:
关闭破真空-关闭吸真空-打开吸真空-延时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;
}

好了,本文章就到这里了,具体区别,需要自己细细体悟,具体用法,需要举一反三

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值