封装
封装、继承和多态是面向对象“三大金刚”。这其中封装可谓三大金刚之首。封装(或称信息隐藏)亦即不对使用者公开类型的内部实现手段,只对外提供一些接口,使用者只能通过这些公开的接口与类型进行交谈。
封装不好实际上继承和多态也是无稽之谈,即使不无稽也会风雨飘摇,使用者可能绕过你精心构造的对象层次,直接访问对象的数据,因为直接访问一切看起来那么自然而然,很简单,很直观也很容易,不需要经过大脑。
面向对象
面向对象是一种将数据和行为绑定在一起的编程方法,虽然在面向过程的时代,也可以使用模块化设计将数据以及使用这些数据的行为绑定在一起,但是毕竟那是靠程序员的个人自律。使用者还是可以轻松的无视这些约定,这样就导致很难发现这块数据有多少地方使用了,如何使用,带来一个问题就是我如果修改这块数据将会带来多大的影响也将是未可知的。面向对象第一次使用强制的手段将数据和行为绑定在一起,但这一切是建立在封装的基础之上的。如果你随意的公开你的数据,那么使用者也就可以随意的使用你的数据,没有人会觉得心里愧疚。因为那毕竟是最直接的手段。这也就是为什么很多人在使用着面向对象的语言干着面向过程的事情的原因。
访问方法
还有一点需要指出的是封装并不是叫你将所有的内部数据都通过getter和setter的方法来访问,套一个简简单单,全裸的方法,就说你是在封装,你说你没有让使用者直接访问数据,你骗谁呢。但是,一些著名的规范或者框架却直接无视三大金刚之首,比如Java Bean,比如像Hibernate之类的ORM。将setter和getter作为规范或标准来执行。不过,没有办法,人家毕竟要通过一种手段来访问你的数据,但是我觉得这种“随意”的要求你将内部敞开的做法不是什么好主意,即使你要访问内部数据,你也要将门槛设高点。还有一点是,大部分时候我们需要在界面上显示数据,收集用户填充的数据,如是我们还是需要一堆的getter和setter。看来getter和setter还是避免不了,但观察上面的问题我们发现,需要公开所有getter和setter的地方是在一些特定的上下文内,并不是所有地方我们都应该热情地敞开胸怀。这样我们就可以根据不同的上下文公开不同的接口来获得更好的封装性。
比如在界面上需要显示或收集数据时,在ORM需要这种getter和setter方法时,我们提供一种宽接口,而在业务逻辑部分我们采用窄接口,因为我不想在业务逻辑计算的时候别的类窥探我的隐私。因为,一旦我能很容易窥探到你的隐私,就总是有这么一种诱惑:根据你的隐私我做出一些决策,而这些决策本应该是你自己做出的,因为毕竟这是你的隐私,你对它最熟悉。比如经常看到如下的代码:
if(String.IsNullOrEmpty(user.Username) && String.IsNullOrEmpty(user.Password))
3: {
//do something
5: }