设计一个保证正确使用的类

时间:2017-10-03 19:07:21

标签: c# class-design

我想了解如何为班级建模。

该类包含方法ABC。这些方法需要按此特定顺序运行,但并非所有方法都是必需的。如果需要,可以拨打AB,而无需致电C

这是一个可能的解决方案:

public void RunA()
{
    A();
}

public void RunAB()
{
    A();
    B();
}

public void RunABC()
{
    A();
    B();
    C();
}

但问题是,我需要在运行A之前处理B的结果,并在运行B

之前处理C的结果

然后工作流程变为:

  • 运行A
  • 处理A
  • 的结果
  • 运行B
  • 处理B
  • 的结果
  • 运行C
  • 处理C
  • 的结果

我设计上述解决方案的方式,这个工作流程是不可能的。我可以允许ABC单独运行,但不再保证操作顺序。

是否有更好的方法来设计此工作流程?

修改

我被问到:

  

“为什么必须按特定顺序调用这些方法?”

要回答这个问题,我必须解释一下这个问题。 ABC,松散地转化为以下步骤:

  • 答:将域模型转换为DTO
  • 处理A的结果:保存转换期间发生的所有异常
  • B:计算并返回有关DTO的一些统计信息
  • 处理B的结果:保存统计信息
  • C:通过API发送DTO
  • 处理C的结果保存提交状态

很明显,A在链中是第一位的。 BC可能是可以互换的,但是为了这个问题,我们假设CB运行之前没有意义。

ABC理论上可以自己处理结果。它主要归结为存储有关结果的信息。但是我想要实现的目标是让班级完全不知道结果的去向。

2 个答案:

答案 0 :(得分:0)

我认为你真正要问的问题是“为什么必须以特定的顺序调用这些方法?”。我认为,如果B要求A被召唤,那不是因为“事情原则”。这是因为A完成了B所需的一些工作。如果是这种情况,那么我只需要让A被称为

public void A() { /* Do Work */ }

然后在B方法中,有类似

的东西
public void B() 
{
    if (!CanProcessB()) {
        throw new Exception("B is not ready, Call A first");
    }

    // Do your work here
}

理想情况下,“CanProcessB”私有方法不只是检查A是否被调用。它实际上验证了内部条件是否正确,以便调用B.据推测,A()会在内部设置一些允许调用B的东西。验证该事物并在未准备好时抛出异常。

这是我至少采取的方法。

编辑:

根本问题似乎是你的班级做得太多了。看来这里有三件“事情”。

域到DTO转换

DTO统计学校准

API来电者

老实说,这些似乎是三个不同的职责,如果您正在寻求实施SOLID设计实践,我认为它们应该是三个不同的类。

DomainToDTOConverter
DTOStatisticsCalculator
ApiInterface

DomainToDTOConverter显然接受域对象,并返回DTO。 DTOStatisticsCalculator接受创建的DTO(因此需要调用A),并返回有关它的统计信息。 ApiInterface通过API发送DTO。

这些可以是三个独立的类,可以彼此独立使用,也可以使单元测试更容易

编辑2:

啊,所以如果你想确保用户获得有关DTO的统计信息,那么你可以将其作为DTO创建过程的一部分返回。因此DomainToDTOConverter使用DTOStaisticsCalculator,并在调用后返回DTO和有关DTO的统计信息。这样,您就知道用户已收到它们。

当然,您无法确保以任何有意义的方式使用这些统计信息。

答案 1 :(得分:0)

解决这个问题的一种方法是利用战略模式。

创建一个通用界面:

public interface IMethod
{
    int MethodSequence { get; }
    void RunMethod();
}

然后你可以拥有自己的方法:

public class MethodA : IMethod
{
    public int MethodSequence => 1;
    public void RunMethod()
    {
        Console.WriteLine("Ran Method A");
    }
}

public class MethodB : IMethod
{
    public int MethodSequence => 2;

    public void RunMethod()
    {
        Console.WriteLine("Ran Method B");
    }
}

public class MethodC : IMethod
{
    public int MethodSequence => 3;
    public void RunMethod()
    {
        Console.WriteLine("Ran Method C");
    }
}

现在创建上下文并按顺序运行方法:

public class RunMethods
{
    public void Execute(IEnumerable<IMethod> methods)
    {
        methods.OrderBy(method => method.MethodSequence)
            .ToList()
            .ForEach(method => method.RunMethod());
    }
}

您的调用代码将成为方法的任意组合:

var runMethods = new RunMethods();

runMethods.Execute(new List<IMethod>
{
     new MethodA(),
     new MethodB()
});