使用返回修改后的父

时间:2017-07-07 10:02:48

标签: c# oop design-patterns

假设我有一个看起来像这样的课程:

class Data
{
    public Data()
    {
       // Stuff
    }

    public void Process1()
    {
       // Stuff
    }

    public void Process2()
    {
       // Stuff
    }
}

我有几种选择如何使用它。最常见的是:

var data = new Data();
data.Process1();
data.Process2();

我喜欢使用的另一种选择要求我修改类:

class Data
{
    public Data()
    {
       // Stuff
    }

    public Data Process1()
    {
       // Stuff
       return this;
    }

    public Data Process2()
    {
       // Stuff
       return this;
    }
}

然后我可以像这样使用它:

var data = new Data().Process1().Process2();

这种类型的写作类属于哪种设计模式(如果有的话)?

2 个答案:

答案 0 :(得分:4)

在我看来,一个流畅的接口上的方法应该返回一个新的源对象实例,该实例由该方法更新。否则很容易写出误导性的代码。

以此代码为例:

public class Data
{
    public double Value { get; private set; }
    public Data(double value) { this.Value = value; }

    public Data Times2Add1()
    {
        this.Value = this.Value * 2.0 + 1.0;
        return this;
    }

    public Data Divide3()
    {
        this.Value = this.Value / 3.0;
        return this;
    }
}

如果我这样做:

var x = new Data(5);
var y = x.Times2Add1();
var z = x.Divide3();

Console.WriteLine(x.Value);
Console.WriteLine(y.Value);
Console.WriteLine(z.Value);

我明白了:

3.66666666666667
3.66666666666667
3.66666666666667

但是,如果我这样写:

public class Data
{
    public double Value { get; private set; }
    public Data(double value) { this.Value = value; }

    public Data Times2Add1()
    {
        return new Data(this.Value * 2.0 + 1.0);
    }

    public Data Divide3()
    {
        return new Data(this.Value / 3.0);
    }
}

结果

5
11
1.66666666666667

当然我可以写var w = x.Times2Add1().Divide3();给我3.66666666666667我得到的,但这一次对我来说更有意义。它成为可测试的健壮代码。

LINQ正确执行 - 例如,在枚举上调用.Where不会改变可枚举,而是返回一个新的。这是编写流畅界面的最佳方式。

当你看到return this;时,即使这是一个流畅的界面,我也会认为它有代码味道。

答案 1 :(得分:0)

查看构建器模式here,它在.net核心启动类中用于通过ConfigurationBuilder对象创建应用程序配置,并使用链接调用:

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", 
        optional: true, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", 
        optional: true)
        .AddEnvironmentVariables();
    Configuration = builder.Build();
}