C# 如何处理时间耦合?

C# 如何处理时间耦合?,c#,oop,decoupling,C#,Oop,Decoupling,我为此而挣扎: 我的类有一些具有时间耦合的方法。也就是说,必须首先调用某个方法MethodA,以“初始化”需要正常工作的MethodB数据 我通常通过将有问题的依赖项作为参数传递给“MethodB”,来明确时间耦合,如以下代码段所示: private class SomeClass { private string field; private int count; public SomeClass() { MethodA();

我为此而挣扎:

我的类有一些具有时间耦合的方法。也就是说,必须首先调用某个方法MethodA,以“初始化”需要正常工作的MethodB数据

我通常通过将有问题的依赖项作为参数传递给“MethodB”,来明确时间耦合,如以下代码段所示:

private class SomeClass
{
    private string field;
    private int count;

    public SomeClass()
    {
        MethodA();
        MethodB(field);
    }

    private void MethodA()
    {
        field = "Something";
    }

    private void MethodB(string str)
    {
        count = str.Length;
    }
}
虽然这让事情变得明确,但我觉得我做错了什么。我最终得到了一个根本不使用字段的方法(静态方法!),因此类开始变得不那么内聚

这是最好的方法吗?(通过传递参数而失去连贯性)


编辑:关于一些建议在构造函数中使用字段作为参数或使用生成器模式来避免无效状态的答案:我不能这样做,因为在我的例子中,我正在构建一个解析器。MethodA读取输入并根据输入设置状态(从文件中读取字符),然后调用MethodB。必须以正确的顺序调用它们。这才是真正的问题:一个应该先调用另一个。

您可以从
MethodB
中删除参数并使用
字段,这样您就不会失去内聚性

private class SomeClass
{
    private string field;
    private int count;

    public SomeClass()
    {
        MethodA();
        MethodB();
    }

    private void MethodA()
    {
        field = "Something";
    }

    private void MethodB()
    {
        count = field.Length;
    }
}
注意事项:

1) 您描述问题的方式似乎像模板方法设计模式,您应该这样做


2) 不属于
那类

我不知道您的确切目标是什么,但为什么不将参数放入类的构造函数中:

private class SomeClass
{
    private string _field;
    private int _count;

    public SomeClass(string field)
    {
        _field = field;
        _count = field.Length;
    }

}
现在你会有这样的东西

SomeClass sc = new SomeClass("Something");//or whatever you want for field.

我想您需要进行一种复杂的初始化,在实际初始化对象之前必须指定一些参数,并且您需要更好地控制类用户正在做什么以避免无效状态。解决这种情况的一个众所周知的模式是所谓的“构建器模式”,它在OOP中非常常用。我不想指出一篇特别的文章,你会发现仅仅使用关键字“builder pattern”就有很多例子。最后,总体思路是创建一个流畅的方法序列,指定内部字段的值,并委托一个最终的方法“Build”来创建一个工作对象实例,并验证传递的参数

Fluent API通过在适当的情况下不在“builder”对象中公开依赖方法来解决公共接口上的此类问题:

SomeClass someInstance = SomeClassBuilder(x=> { 
     x.MethodA().MethodB("somevalue");
});
这需要更多的管道,因为您需要构建器对象,以及构建器组件,例如从MethodA返回的对象,该对象公开MethodB。这样,调用MethodB的唯一方法是首先调用MethodA


我不鼓励您采用这种方法。对于许多场景来说,这可能是过火了,但在遇到合适的场景时,注意这个选项是很重要的。

如果您遵循贫血领域模型,您可以将您的类拆分为两个较小的类。您会意识到糟糕的设计,因为您当前的类违反了,简言之,它有2个职责:1个负责处理输入过程,1个负责处理输入结果

将其分解,以便
ClassA
将处理输入和返回的结果,然后
ClassB
ClassA
的结果作为参数,然后对其进行处理。例:

public class ClassA
{
    public string MethodA()
    {
        // read the input
        return "Something"; // or return the input
    }
}

public class ClassB
{
    private int count;
    public void MethodB(string str)
    {
        count = str.Length;
    }
}
如果您发现这两个类的使用都很麻烦,请使用另一个类。例:

public class ClassC
{
    public ClassA ClassA = new ClassA();
    public ClassB ClassB = new ClassB();
    public void Execute(){
        string result = ClassA.MethodA();
        ClassB.MethodB(result);
    }
}

你是担心你的私有方法中的内聚力,还是这是一个人为的例子?@neontapir:更高的内聚力听起来不像是他应该担心的事情。这在技术上是错误的。静态方法只能属于一个类。它们不属于实例。你指的是什么静态方法,@ThorstenDittmar?所有这些在我看来都像实例方法。@ThorstenDittmar你是对的,静态方法必须放在一个类中,但不能放在那个类中。@neontapir adricadar说静态方法不属于一个类。好吧,我明白你的意思,但真正的问题是我正在构建一个解析器,它以顺序的方式读取字符,所以MethodA从输入中读取,将一些字段设置为有效状态,然后调用MethodB。您无法预测输入。Builder在某些情况下非常好,但是这种情况如何?为什么要在解析器类中读取文件?我不明白,或者你的方法与坚实的原则相冲突?我实际上认为这是解决这个问题的可行方法。完美的解决方案