特 2014-12-01
面向对象设计原则之单一职责原则和开闭原则
面向对象的语言依然是现在的主流语言,面向对象的开发方式相比面向过程的开发方式可以提高系统的可维护性和可重用性,在支持可维护性的同时提高系统的可复用性是一个至关重要的问题,如何提高一个软件系统的可维护性和可复用性是面向对象设计需要解决的核心问题。因此作为面向对象的开发者很有必要去深入理解面向对象语言的设计思想。
记得在软件体系结构课上提到,一个软件系统应该是由构件和连接件组成,另外还有约束指出系统如何将这些构件和连接件组合起来。那么我们在写代码的时候要尽量的去制造一些构件和连接件,在我们下次开发系统的时候就可以像组装汽车零件那样来开发我们的系统。在软件工程的思想里面组装构建的方式可以大大降低系统模块之间的耦合,降低开发成本。那么如如何制造高内聚,低耦合的组件也是一种别样的技术,也是我们学习程序设计语言的重要方向。
我们要做好的设计就必须按照这些面向对象的设计原则,抛弃以前那些过于僵硬、过于脆弱、复用率低、粘度过高的设计方案灵活运用这些原则实现系统的可扩展性、灵活性、可插入性使得系统可维护性、可复用性大大增强,每种设计原则都值得开发和设计人员细细品味。当我听到刘伟老师讲设计模式的时候顿时如饮甘饴,醍醐灌顶。下面来简单介绍一下关于这几种设计原则,当然这些原则也就是评价23种设计模式的依据:
定义:一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中。
类的职责要单一,不能将太多的职责放在一个类中,不能使一个类太累。
单一职责原则是实现高内聚、低耦合的指导方针。
类的职责主要包括两个方面:数据职责和行为职责,数据职责通过属性来体现,而行为职责通过方法来体现。如果一个类的职责太多,将导致系统非常脆弱,一个职责可能会影响其他职责,因此要职责分类,比如负责获取数据库连接的职责就可以单独作为类,负责对数据库层CRUD操作可以做成一个类。负责页面控制职责可以做成一个类,比如菜鸟会把一个类的如下设计:
这个类的职责显然太多,涉及到初始化界面、显示、验证输入、获得数据库连接、业务处理等等。如果一个新的项目过来很显然无论界面还是数据库访问都无法达到复用的目的。我么来看一下下面这种设计方案会不会更好些。
这样的设计把各个职责分给不同的类,虽然类的个数增加,但是类的复用性增强,DBUtil可以供多个DAO使用,UserDAO也可以供不同的类使用。
开闭原则是面向对象的可复用设计的第一块基石,是面向对象设计的目标。一个软件实体应该对扩展开放对修改封闭,也就是说再设计一个模块的时候,应当使得这个模块可以在不被修改的情况下进行扩展,即实现再不修改源代码的情况下通过实现或者继承扩展系统。为了满足开闭原则,我们需要对系统进行抽象化设计,抽象化是实现开闭原则的关键。开闭原则也是实现组件化编程的基础。
假如一个图形界面提供了不同的形状的按钮,客户可以针对这些形状进行编程,最初的设计可能是这样的
假如我们需要换一种按钮形状,我们需要将CircleButton修改成RectangleButton类那么我们需要修改源代码,由于这两个按钮类中的方法不同因此我们还需要修改LoginForm中的dispaly方法,不满足开闭原则,设计不够灵活。
上述是面对具体的类进行编程,每次更换集体的类时都需要修改源代码,而且类中没有统一的接口,不满足开闭原则,要满足开闭原则要对按钮类进行抽象化,抽取一个抽象类AbstactButton,LoginForm类针对抽象类AbstactButton进行编程,在JAVA中可以通过配置文件、DOM解析技术、反射机制将类名存储在配置文件中,在运行时生产其对象实例,我们需要修改按钮的类型的时候我们只需要修改配置文件。重构后其满足开闭原则:
因为XML和properties等格式的配置文件时纯文本文件,可以直接编辑不需要编译,因此修改配置文件并不属于修改源代码