C# 一种适用于条件模型中大型条件的设计模式

C# 一种适用于条件模型中大型条件的设计模式,c#,design-patterns,C#,Design Patterns,我正在重写一个野兽般的程序,它无所不能,而且是厨房水槽。这是一个电话IVR系统(按1到布拉,按2到…)我已经将它的所有功能划分到了自己的项目中,但是我最大的一个痛点是当我们第一次接听电话时,让用户输入一个代码,让我们知道将呼叫发送到哪个系统 整个代码系统乱七八糟,但无法更改,我已将大约800行VB6重构为类似以下代码的内容: string code = foo.GetAccessCodeFromCaller(); if (DatabaseCheck1(code) { parse = Pa

我正在重写一个野兽般的程序,它无所不能,而且是厨房水槽。这是一个电话IVR系统(按1到布拉,按2到…)我已经将它的所有功能划分到了自己的项目中,但是我最大的一个痛点是当我们第一次接听电话时,让用户输入一个代码,让我们知道将呼叫发送到哪个系统

整个代码系统乱七八糟,但无法更改,我已将大约800行VB6重构为类似以下代码的内容:

string code = foo.GetAccessCodeFromCaller();
if (DatabaseCheck1(code)
{
    parse = ParseCode(code);
    dbValue = GetSomethingFromDB(parse);
    if (OtherCheck1(dbValue)
    {
        // Launch the Pay Taxes project.
    }
    else if (OtherCheck2(dbValue)
    {
        // Launch the Uploaded File project
    }
    else
    {
        // Schedule Something or other project
    }
}
else if (LookForSomethingElseInDB(code)
{
    parse2 = AltParseMethod(code)
    if (Conditional(parse2))
    {
        if (LargeChunkOfCodeConditional(code))
        {
            // Report a something or other project.
        }
        else
        {
            // Talk to Tech Support.
        }
    }
    else
    {
        // Invalid Input
    }
}
else
{
    if (YetAnotherChunkOfCode(code))
    {
        // Order products project
    }
    else
    {
        // Invalid Input.
    }
}
我需要一个好的体系结构来正确地完成这个系统,正确的体系结构等同于具有高度的适应性,可以让更多的垃圾鞋进入它。最初的系统是在VB4/5中完成的,经过了16年的近月变化。我想要的东西能让这乱七八糟的局面保持有序,并且在接下来的16年里很容易添加垃圾

到目前为止,我已经尝试了一些模式(Visitor和Command),但似乎没有什么适合我尝试实现它的方式。如果您有任何建议,我们将不胜感激

编辑: 更清楚一点,我当前的体系结构有以下项目的解决方案:Dispatch、Paytax、UploadedFiles、ScheduleSomething、ReportSomething、TechSupportRedirect、OrderProducts等。。。(以及硬件应用、共享接口和数据库访问项目)。Dispatch使用HardwareAbstraction项目接听电话并询问呼叫者代码,然后将呼叫路由到其他10个执行完全不同任务的项目中的一个(然后可以由10个不同的开发人员并行重写,而不会被踩到)


我可以很好地理解目标项目的体系结构,但是实际的调度项目让我很困惑。另外,如果我的整个解决方案体系结构是某种反模式的,有人会在我走得太远之前告诉我。

也许你需要的只是一个简单的提取方法,将大量内部条件排除到单独的方法。

我对VB6一无所知,但是如何将代码映射到“委托”呢(不知道VB6中是否存在这个概念)。其思想是:输入代码是返回要调用的方法的字典的“键”(如果找不到这样的代码,则为空/空/无)

更新: 如果这是用C#写的,你就不能把代码放到

Dictionary<string, Action> OpCodes;
更新2: 似乎你有“层”的条件。我想这会映射到“字典中的字典”。但考虑到这个问题:用户键入一系列选择,这些选择应该以某种行为结束,听起来像:为每个系统行为定义“委托”,并映射到代码:

比如:


如果您重写它以创建不同的类来处理不同的代码,那么可能会使您的代码库更易于维护

差不多

var codeHandler = CodeHandlerDecider.GetCodeHandlerFor(
    foo.GetAccessCodeFromCaller());
codeHandler.HandleCode();
然后,您的CodeHandlerDecider将执行以下操作:

public static ICodeHandler GetCodeHandlerFor(string code)
{
    if (DatabaseCheck1(code)
    {
        return new FirstCodeHandlerClass(code);            
    }
    else if (LookForSomethingElseInDB(code)
    {
        return new SecondCodeHandlerClass(code);            
    }
    else
    {
        return new ThirdCodeHandlerClass(code);
    }
}
然后一个示例类是

public class FirstCodeHandlerClass: ICodeHandler
{
    public void HandleCode(string code)
    {
        parse = ParseCode(code);
        dbValue = GetSomethingFromDB(parse);
        if (OtherCheck1(dbValue)
        {
            // Launch the Pay Taxes project.
        }
        else if (OtherCheck2(dbValue)
        {
            // Launch the Uploaded File project
        }
        else
        {
            // Schedule Something or other project
        }
    }
}
界面看起来像

public interface ICodeHandler
{
    void HandleCode();
}

这听起来像是一项工作!你甚至可以想象并创建一个外部DSL,因为状态机非常适合于此。事实上,我刚刚发现它似乎使用电话系统作为其主要示例。

这类问题有两种常见模式:

1) 子类化/继承以实现多态调度

2) 表驱动编程

基本思想是将允许您做出决策的信息放在表中,然后编写遍历表的代码。如果你从一个有趣的角度思考,多态方法就是直接构建到语言中的表驱动编程。表驱动技术为您提供了以下好处:更具声明性、更小的代码大小、易于扩展/添加新案例、更清晰


正如其他人所指出的,您可以使用字典来实现此模式。

多亏了这里的所有人,由于这些建议,我克服了一些心理障碍,发现责任链模式将很好地解决我的问题。

我正在用C#重写整个项目,因为管理层决定购买的硬件有一个非常干净的.net API。考虑一下:代码1002*34567是我们的一种格式。为了处理它,我们在*(客户概要1002)之前查找客户概要。如果该配置文件存在,那么什么操作与34567匹配。基本上,将所有可能的代码组合存储在字典中是困难的,而且它会不断变化。比如说有人上传了一个文件,文件被拒绝了,两分钟后,他们打电话给客户服务部,告诉他们拒绝访问代码,我明白你的意思。当用户插入数字时,“做什么”似乎是唯一确定的。如“按2键进行客户服务…输入拒绝访问代码”。。。这就是我用“层”暗示的。让第一个数字映射到字典,直到您唯一地确定了要做什么(调用什么委托)。@Yogin,听起来像是“代码”是用户按下的菜单选项,但现在似乎代码是各种输入的组合,包括用户对提示的响应(例如,“输入您的信用卡号”)。对吗?
public class FirstCodeHandlerClass: ICodeHandler
{
    public void HandleCode(string code)
    {
        parse = ParseCode(code);
        dbValue = GetSomethingFromDB(parse);
        if (OtherCheck1(dbValue)
        {
            // Launch the Pay Taxes project.
        }
        else if (OtherCheck2(dbValue)
        {
            // Launch the Uploaded File project
        }
        else
        {
            // Schedule Something or other project
        }
    }
}
public interface ICodeHandler
{
    void HandleCode();
}