一种用于条件中的大条件的设计模式

本文关键字:条件 设计模式 用于 一种 | 更新日期: 2023-09-27 18:09:34

我正在重写一个野兽程序,它做了所有的事情,它是厨房水槽。这是一个电话IVR系统(按1到blah blah,按2到…)我已经把它的所有功能分成了各自的项目,但是我最大的痛点是当我们第一次接电话时,让用户输入一个代码,让我们知道把打电话的人分配到哪个系统。

整个代码系统是一团糟,TBH,但它不能改变,我已经重构了大约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),但似乎没有一个适合的方式,我试图实现它。如有任何建议,我将不胜感激。

编辑:为了更清楚一点,我目前的架构有以下项目的解决方案:调度,PayTaxes, UploadedFiles, ScheduleSomething, ReportSomething, TechSupportRedirect, OrderProducts等…(以及硬件抽象、共享接口和数据库访问项目)。Dispatch使用硬件抽象项目来接听电话并请求调用者代码,然后将调用路由到执行完全不同任务的其他10个项目中的一个(然后可以由10个不同的开发人员并行重写,而不会受到伤害)。

我可以很好地理解目标项目的体系结构,但是实际的Dispatch项目却把我绊倒了。此外,如果我的整个解决方案架构是某种反模式,请在我走得太远之前告诉我。

一种用于条件中的大条件的设计模式

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

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

里吗?
Dictionary<string, Action> OpCodes;

然后像这样做:

if(OpCodes.ContainsKey(code))
  OpCodes[code]();
更新2:

看来你有"层层"条件句。我想这将映射到"字典的字典"。但是想想这个问题:用户键入一系列选择,这些选择应该以某种行为结束,听起来像:为每个系统行为定义"委托",并映射到代码:

:

OpCodes["123"] = new Action(TechSupport.StartConversation);

也许你需要的只是一个简单的ExtractMethod来排除大型的内部条件体来分离方法

感谢这里的每个人,由于他们的建议,我克服了一些心理障碍,发现责任链模式将很好地解决我的问题。以下是关于如何实现它的MSDN文章。

如果你重写它来创建不同的类来处理不同的代码,这可能会使你的代码库更易于维护。

之类的
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,因为状态机非常适合这样做。事实上,我刚刚在codeplex上发现了一个项目,它似乎使用了一个电话系统作为它们的主要示例。

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

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

2)表驱动编程

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

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