如何设计Fluent界面?

Afr*_*Ali 3 c# fluent-interface fluent

我一直试图为我的一个框架设计一个流畅的界面,似乎我无法理解这个难题的一部分.我知道我可以使用接口和类来驱动我想要调用哪些方法.但请考虑以下方案.

让我说我有一个Person类,我希望能够做类似的事情

Person.WithName("Steve").WithAge(18).Save();
Run Code Online (Sandbox Code Playgroud)

同样地,我也希望我的API的调用者做类似的事情

Person.WithName("Steve").Save();

or

Person.WithAge(18).Save();
Run Code Online (Sandbox Code Playgroud)

但我不希望用户单独调用save方法

Person.Save();
Run Code Online (Sandbox Code Playgroud)

现在,如果我想设计这样的API,我该如何实现它?如果我从WithName和WithAge方法返回Person类的实例,那么我必须将Save方法放在Person类中,这意味着用户可以直接调用它.

Jay*_*Jay 5

如您所示,您可以使用界面来控制可见内容.使用显式接口实现可以在某些情况下隐藏方法,并在其他情况下公开它们.它还允许您使用多个具有相同签名的方法.

在这种情况下,我们有一个私有构造函数,因此只能使用其中一个静态入口点创建Person.一旦我们有了名字或年龄,我们就会返回一个人的实例,并且可以调用WithName,WithAge或者Save.

public class Person : IPersonBuilder
{
  private string _name;
  private int? _age;

  private Person() { }

  public static IPersonBuilder WithName(string name)
  {
    return ((IPersonBuilder)new Person()).WithName(name);
  }

  public static IPersonBuilder WithAge(int age)
  {
    return ((IPersonBuilder)new Person()).WithAge(age);
  }

  IPersonBuilder IPersonBuilder.WithName(string name)
  {
    _name = name;
    return this;
  }

  IPersonBuilder IPersonBuilder.WithAge(int age)
  {
    _age = age;
    return this;
  }

  public void Save()
  {
    // do save
  }
}

public interface IPersonBuilder
{
  IPersonBuilder WithName(string name);
  IPersonBuilder WithAge(int age);
  void Save();
}
Run Code Online (Sandbox Code Playgroud)

如果Person是一个具有超出流畅界面的意义的类 - 它是某种实体 - 那么我将创建一个静态入口点,它返回一个PersonBuilder对象并将所有其他流畅的关注点移出Person.