本节书摘来自异步社区《设计模式解析(第2版•修订版)》一书中的第1章,第1.7节面向对象程序设计实践,作者【美】Alan Shalloway(艾伦•沙洛维) , James R.Trott(詹姆斯•R.特罗特),更多章节内容可以访问云栖社区“异步社区”公众号查看。
1.7 面向对象程序设计实践
设计模式解析(第2版•修订版)
我们再次考察一下本章开始讨论的形状实例。怎样用面向对象的方式实现它呢?请记住,我们必须完成以下任务。
1.在数据库中找到形状列表。
2.打开形状列表。
3.按某种规则将列表排序。
4.在显示器上显示各个形状。
为了用面向对象方式解决这个问题,我需要定义一些对象和这些对象具有的责任。
在Shape程序中使用对象
所需要的对象如下表所示。
运行程序
现在主程序的步骤应该与下面给出的类似。
1.主程序创建一个数据库(ShapeDataBase)对象的实例。
2.主程序要求数据库对象找到我感兴趣的一组形状,然后实例化一个保存这些形状的Collection对象(实际上,它还将实例化Collection对象中存放的Circle对象和Square对象)。
3.主程序要求Collection对象将所存放的形状排序。
4.主程序要求Collection对象显示形状。
5.Collection对象要求所存放的所有形状显示自己。
6.每个形状根据形状种类显示自己(使用Display对象)。
为什么这有助于应对新需求
我们来看这个方案怎么会有助于我们应对新的需求(请记住,需求总在变化)。例如,考虑如下的新需求。
增加新种类的形状(例如三角形)。为了引入一种新的形状,只需两步:
创建Shape类的一个新的派生类,来定义这个新形状;
在新的派生类中,实现与该形状对应的display方法。
修改排序算法。为了修改形状排序方法,只需一步:
修改Collection的sort方法。这样所有形状都将使用新算法。
结论:面向对象方法有效地限制了需求变更所带来的影响。
再谈封装
封装有几个优点。“对用户隐藏”这一事实直接蕴涵了以下优点。
使用更容易,因为用户不需要再操心实现问题了。
可以在不考虑调用者的情况下修改实现。(因为调用者从一开始就不知道对象是如何实现的,它们之间不应该存在任何依赖关系。请记住,在维护中时间往往花在了解和留心这些依赖关系上,而不是实际添加新功能。)
其他对象对该对象内部是未知的——这些外部对象往往用来帮助实现该对象接口所指定的功能。
优点:减少副作用
最后,考虑功能改变时引起的不良副作用问题。这种bug通过封装有效地解决了。对象内部对于其他对象是未知的。如果使用封装,并遵循“对象自己负责自己”的策略,那么唯一能影响对象的办法就是调用该对象的方法。对象的数据和实现其责任的方式都与其他对象所带来的变化屏蔽开来。
封装拯救了我们
对象对自己行为所负的责任越多,控制程序需要负的责任就越少。
封装使对象内部行为的变化对其他对象变得透明了1。
封装有助于防止不良副作用。
值得注意的是封装与耦合的关系。封装什么东西时,必然将使其耦合变松。隐藏实现(即封装它们)有助于松耦合。
1即不可见了。——译者注
本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。