如何处理时间耦合?

时间:2015-04-07 19:18:47

标签: c# oop decoupling

我因此而苦苦挣扎:

我的类有一些具有时间耦合的方法。也就是说,必须先调用某些方法 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;
    }
}

虽然它使事情明确,但我觉得我做错了什么。我最终得到了根本不使用字段的方法(静态方法!),所以这个类开始变得不那么紧密了。

这是最好的方法吗? (通过传递参数失去凝聚力)

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

5 个答案:

答案 0 :(得分:4)

如果您遵循Anemic Domain Model,您可以打破您的班级,并使其成为2个较小的班级。你意识到设计不好,因为你当前的类违反了SRP,简而言之它有2个责任:1用于处理输入过程,1用于处理输入结果。

将其分解,以便ClassA处理输入并返回结果,然后ClassBClassA的结果作为参数,然后处理它。例如:

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;
    }
}

如果您发现同时使用这两个类很麻烦,请使用另一个aggregate service。例如:

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

答案 1 :(得分:3)

我想你需要进行一种复杂的初始化,其中必须在实际初始化对象之前指定一些参数,并且你希望更好地控制类用户正在做什么以避免无效状态。解决这种情况的一个很好的知识模式是所谓的" Builder Pattern",在OOP中经常使用。我不想指出一篇特定的文章,你会发现自己有很多例子,只需使用关键字" builder pattern"。为了完整,总体思路是制定一个流畅的方法序列,指定内部字段的值,并委托最终方法" Build"创建工作对象实例,并验证传递的参数。

答案 2 :(得分:3)

Fluent API通过不在" builder"中公开依赖方法来解决公共接口上的这种问题。对象直到适当:

SomeClass someInstance = SomeClassBuilder(x=> { 
     x.MethodA().MethodB("somevalue");
});

这需要更多的plumbling,因为您需要构建器对象,以及构建器组件,例如从MethodA返回的公开MethodB的对象。这样,调用MethodB的唯一方法是首先调用MethodA。

我不鼓励你采用这种方法。对于许多情况来说可能有些过分,但是如果你遇到这样的情况,请务必注意这个选项。这是合适的。

答案 3 :(得分:1)

您可以从MethodB中删除参数并使用field,这样就不会失去凝聚力

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)您描述问题的方式似乎是模板方法设计模式,您应该have a look here

2)Static methods不属于那个

答案 4 :(得分:0)

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

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.