我一直在尝试为我的一个框架设计一个流畅的界面,似乎我无法理解其中一个难题。我知道我可以使用接口和类来驱动我想要调用哪些方法。但请考虑以下方案。
让我说我有一个Person类,我希望能够做类似
的事情Person.WithName("Steve").WithAge(18).Save();
Simmilarly我也希望我的API的调用者能够执行类似
的操作Person.WithName("Steve").Save();
or
Person.WithAge(18).Save();
但我不希望用户单独调用save方法,如
Person.Save();
现在,如果我想设计这样的API,我该如何实现它?如果我从WithName和WithAge方法返回Person类的实例,那么我必须将Save方法放在Person类中,这意味着用户可以直接调用它。
答案 0 :(得分: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();
}
如果Person
是一个超出流畅界面的意义的类 - 它是某种实体 - 那么我会创建一个静态入口点,返回一个PersonBuilder
对象并移动所有其余的流畅问题来自Person
。
答案 1 :(得分:4)
您可能希望区分创建和属性设置。也许你想要这样的东西:
public interface IPerson
{
IPerson WithName(string name);
IPerson WithAge(int age);
}
public class Person : IPerson
{
//You can also add required parameters here. That'll
//ensure that a person is not saved before his specifications
//are atleast minimally specified.
public Person() { }
}
new Person().WithAge(18).WithName("Steven").Save();
或者,如果你只是希望开发人员能够建立一个人而不鼓励修改后的人。
public interface IPersonBuilder
{
IPersonBuilder WithName(string name);
IPersonBuilder WithAge(int age);
IPerson Save()
}
public interface IPerson
{
public string Name { get; }
public int Age { get; }
}
public class PersonBuilder
{
public PersonBuilder() { }
}
new PersonBuilder().WithAge(18).WithName("Steven").Save();