程序设计之封装/信息隐藏(Information Hiding)

好的类的接口应该像冰山的尖一样,让类的大部分内容(类的内部工作机制)都不被暴露出来。内部内部实现细节应该尽可能的隐藏,这种设计策略可以减少“改动所影响的代码量”。

信息隐藏主要针对两点:

  • 隐藏复杂度
  • 隐藏变化源,这样当发生变化时,其影响就可以被限制在局部

设想我们有个类,他的每个对象都有名为id的变量来保存一个唯一的ID,同时用一个名为g_maxId的全局变量保存当前已经分配的最大ID,当我们创建一个新的对象时,只要在构造函数中使用id = ++g_maxId这条语句,就能获得一个唯一的ID值。想想这种设计会有什么问题吗?

针对上面那个类,如果我们要:

  • 将某个范围的ID保留,用作其他用途
  • 使用非连续的ID提高安全性
  • 重新使用已经销毁的ID
  • 添加一个断言,确保ID不会超过最大值
  • ID的类型发生变化

如果我们的代码中到处都是id = ++g_maxId这种代码的话,出现以上情况的话,这些代码处处都需要修改,另外这种代码也不是线程安全的(thread-safe)。

良好的设计应该是这样:

  • id = NewId(), 通过NewId函数封装ID的生成规则,这样的话无论NewId内部做的多复杂都不会影响到外面
  • id有可能是int,有可能是string,对于C++,可以使用typedef把ID定义为IdType,这样如果id类型发生了变化,程序内部使用id的地方不用做修改