名可名,非常名--谈接口和实现
黄国强 2009-9-22
“名可名,非常名”出自《老子》第一章,解释有多种,我找了一个请见[1]。在这里我借这段话来引出接口和实现的话题。
平时我非常喜欢举的例子是桌子。比如,我们把桌子设计成一个类。
问题很快出现了,我们应该给这个桌子增加什么成员函数呢?加上有几条腿的查询函数?加上是什么颜色的查询函数?感觉正好应了“名可名,非常名”这句话。我们根本无法用类来表达我们生活中这样一个常见的概念。
这个问题产生的原因是什么呢?
我认为,问题出在我们只从一个角度看这个问题。这里需要的是两个角度即,一个是使用者的角度(即,名可名),一个是实现者的角度(即,非常名)。有两个用 户,一个需要书桌(desk),一个需要餐桌(table)。从这两个使用者的角度可以获得两个接口类IDesk和ITable,从实现者的角度可以得到 具体类CTableImplement。CTableImplement 从二者继承。代码如下。
//负责表示书桌
class IDesk
{
...
};
//负责表示餐桌
class ITable
{
...
};
class CTableImplement
: public IDesk
, public ITable
{
...
};
任何接口类的设计都是不能孤立进行的,一定要放在一个具体环境中。桌子这个例子同样如此。观察一个使用者如何使用者张桌子(比如用来当饭桌),从这个角度 我们很容易的给ITable定义出成员函数。一张桌子到底被别人怎么用,桌子本身是无法知道的。所以具体类 CTableImplement 的设计无需从使用者的角度来考察。仅仅需要按照设计者的常识设计桌子即可,无需关注使用者。设计完成后,再去实现从IDesk和ITable继承的虚函数。这点与接口设计存在非常明显的不同。