在一个类中混合流畅和不流畅的界面

时间:2009-07-06 23:04:44

标签: class-design fluent-interface

我认为流畅的界面非常便于许多任务。但是当我最终在一堂课中混合流利的方法和修改方法时,我感到不安。

只是一个例子(它有点做作,请耐心等待):

假设一个字符串实用程序类,修剪似乎很适合链接:

Str & Str::Trim() { return TrimLeft().TrimRight(); }

其他方法自然会返回一个新对象:

Str Str::GetFirstToken() const
{ 
   // result = first token;
   return result;
}

还有第三种类型 - 它本身 - 会逻辑地改变对象并且返回一个新对象:

Str Str::SplitFirstToken() 
{ 
   result = GetFirstToken();
   // this = remainder
   return result;
}

当我使用每个方法最明显的签名时,我最终会得到这三种类型,我担心这种类型的消费不是很直观,特别是因为返回类型是mroe或更少同样的。


我已经决定不让Str成为不可变的 - 因为像SplitToken这样的方法提供了核心功能。我的主要问题是混合流畅的方法你会做什么?

  • 不要在该界面中使用流畅的方法

  • 将它们移至子界面(见下文)

  • “如果一个人流利,所有修改方法都应该流利”?

  • 为流利方法使用seocific前缀?

  • 别担心?

  • ???

子界面的想法:

void CStr::Trim() { TrimLeft(); TrimRight(); }
CStrFluent & Str::Fluent() { return CStrFluent(*this); }
....
str.Fluent().TrimLeft().TrimRight();

我对此尚未决定,我不太喜欢额外的“流利” - 尤其是它是C ++中的方法调用

您怎么看?

[edit]我在这里使用“流利”的基本含义是在单个实例上链接方法调用,而不是在代码中创建英语句子的高级意义。

1 个答案:

答案 0 :(得分:3)

我没有用流畅的界面做很多工作(尽管我一般都使用过DSL),但在我看来,虽然这个类可能适合这种方法,但在这种情况下并不是特别必要。也许我错过了一些东西,但在我看来,你不可能在单个字符串上做一堆操作而没有引用任何其他东西,这就是你最终在这里得到的东西。此外,您正在转换到链中间的新对象,这似乎再次违反了流畅界面的目的,特别是当您考虑此链中发生的事情时:

Str String = OtherString.GetFirstToken().SplitFirstToken().Trim();

我想也许这种类型的相对低级的实用程序类是尝试流畅的接口的错误位置。当你的对象受到持久的,集中注意力而不是它们是瞬态和辅助核心逻辑时,流畅似乎对我来说更为重要。