在大学里学习C++的时候,老师说C++是一门面向对象的语言,面向对象的三大特征是封装、继承和多态。什么是封装呢?一般来说封装就是隐藏类的数据成员,只向外提供一些公用的操作接口,只能通过这些接口来操作类的数据成员,而不能直接对这些数据成员进行赋值改变等操作。这样做的好处是什么呢?如果选择直接暴露数据成员,有些人可能会把这些成员修改为非法数据导致程序出错。所以封装了操作数据成员的细节,能够对新值进行验证或者其他操作等。

  所以一直以来我对封装的理解就是隐藏数据成员,通过接口来操作它们。

 public class Person
 {
     //...
     private int _Age;
     public int Age
     {
         get
         {
             return _Age;
         }
         set
         {
             if(value >= 0)
                 _Age = value;
         }
     }
 }

  但是这种理解是很初级的,封装是面向对象中很重要的一环,它不仅仅表示隐藏数据成员,它还表示封装变化,有一句很有名的话:Encapsulate what varies. 它告诉我们只要是会变化的,就要封装它!用好封装这一面向对象的基本准则,能够让我们的软件系统更具有扩展能力和弹性,能更好的应付变化或者扩展的需求。因为在软件开发中,唯一不变的就是变化。

  下面用例子来说明封装一切可能的变化。比如我们要写一个Person类,记录一些Person的基本信息:

 public class Person
 {
     private string _FirstName;
     private string _LastName;
     private int _Age;
     private bool _Sex;
     private string _IdentityID;
     private float _Stature;
     private Country _Nationality;
     //...

     public Person(string firstName, string lastName,...)
     {
         //...
     }
 }

当然可能还有其它字段,这里也不一一列举了。但是需求是很容易改变的,可能突然有一天,客户要增加一些信息,比如就职单位,毕业学校等等。如果按照上面的设计类的改动是必不可少的,增加字段,修改构造函数,使用到Person类的地方可能都要进行修改。这时就会有人提出要对Person类进行重构,因为信息字段很容易变化,增加或者删除,所以要封装它们。

 public class Person
 {
     private string _FirstName;
     private string _LastName;
     private string _IdentityID;

     public Person(string firstName, string lastName, 
         string identityID, PersonInfo info)
     {
         //...
     }
 }

 public class PersonInfo
 {        
     private int _Age;
     private bool _Sex;
     private float _Stature;
     private Country _Nationality;
     //...
 }

  现在看来Person类和PersonInfo类进行关联,所有的个人信息都放在PersonInfo类中进行保存,如果需要增加或者删除信息字段的时候,只需要改动PersonInfo类就 可以了而不用修改Person类。不过这样做我们还是需要修改PersonInfo类,所以又有人提出另一种重构方案:

 public class Person
 {
     private string _FirstName;
     private string _LastName;
     private string _IdentityID;
     private Hashtable _Information;

     public Person(string firstName, string lastName,
         string identityID)
     {
         //...
     }
 }

  把Person的个人信息都封装在一个Hashtable中,不管这些字段是不是需要变化,代码都不需要改变。(当然这种方案也不一定是最好的,只是一种参考)

  由此可以看到封装的威力,它使系统更具有弹性,当遇到变化的时候,我们可以自由应对。当然封装不仅仅用于字段,还可以用于封装行为,在《Design Patterns Explained》里面有很好的解释和示例,有时间下次再写。

  这句话一定要记住:Encapsulate what varies.

 

 

 

 posted on 2007-08-06 10:27  紫色阴影  阅读(1716)  评论(11编辑  收藏  举报
我要啦免费统计