首页 > 代码库 > 六大设计原则
六大设计原则
1. 单一职责原则(SRP: Single Resposibility Principle)
用“职责”或“变化原因”来衡量接口或类设计得是否优良,但“职责”和“变化原因”都是不可度量,因项目而异。
好处:
类的复杂性降低,职责有清晰明确的定义
可读性提高
可维护性提高
变更引起的风险降低
例如:属性、行为分开。
我单纯,所以我快乐。
最佳实践:接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化。
2. 里氏替换原则(LSP: Liskov Subsititution Principle)
继承优点:代码共享,提高代码重用性,形似父类又异于父类,提高代码的可扩展性,提高项目或产品的开放性
继承缺点:侵入性,降低灵活性,增强耦合性
如何扬长避短?LSP为良好的继承定义了一种规范。
检验标准:只要父类能出现的地方,用子类替换后,不会产生任何异常和错误。说明符合LSP规范。
四层含义:
子类必须完全实现父类的方法。
做系统设计时,经常会定义一个接口或抽象类,调用类直接传入接口或抽象类。
在类中调用其他类时,务必要使用父类或接口,否则类的设计违背LSP原则。
如果子类不能完整实现父类的方法,或者父类的某些方法在子类中已经发生”畸形“,则建议断开父子继承单位,采用依赖、聚集、组合等关系代替继承。
子类可以有自己的个性。
覆盖或实现父类的方法时输入参数可以被放大
覆盖或实现父类的方法时输出结果可以被缩小
采用LSP目的:增强程序健壮性,版本升级保持非常好的兼容性。
3. 依赖倒置原则(DIP: Dependence Inversion Principle)
模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系通过接口或抽象类产生的
接口或抽象类不依赖于实现类
实现类依赖接口或抽象类
一句话:面向接口编程
采用DIP目的:
减少类间的耦合性:发生变更时可检验是否松耦合。
提供系统稳定性:稳定性较高的设计,在周围环境频繁变化的时候,依然可以做到”我自岿然不动“。
降低并行开发引起的风险:否则很难实现并行开发。两个类之间有依赖关系,只要制定出两者之间的接口或抽象类就可以独立开发了。项目之间的单元测试也可独立运行。TDD(Test-Driven Development, 测试驱动开发)模式是LSP的最高级应用。JMock工具可以根据抽象虚拟一个对象,用于测试。TDD,先写好单元测试类,在写实现类,特别适合研发类项目或项目成员整理水平较低的情况下采用。
提高代码的可读性和可维护性。
依赖三种写法:
构造函数传递依赖对象(构造注入)
Setter方法传递依赖对象(setter注入)
接口声明依赖对象(接口注入)
最佳实践:
每个类尽量都有接口或抽象类,或者抽象类或接口两者都具备
变量的表面类型尽量是接口或者抽象类
任何类都不应该从具体类派生
尽量不要覆写基类的方法
结合LSP原则使用
通俗的规则:接口负责定义public属性和方法,并且声明与其他对象的依赖关系;抽象类负责公共构造部分的实现;实现类准确实现业务逻辑,同时在适当时候对父类进行细化。
4. 接口隔离原则(Interface Segregation Principle)
定义:建立单一接口,不要建立臃肿庞大的接口。即接口尽量细化,同时接口中的方法尽量少。
与单一职责原则不同。一个从业务角度划分职责;一个是里面的方法不要太多,否则权限控制不便,即与调用者无关的方法都暴露出来了。
4层含义:
接口要尽量小:根据接口隔离原则拆分接口时,首先必须满足单一职责原则
接口要高内聚【高内聚:提高接口、类、模块的处理能力,减少对外交互】:要求接口中尽量少公布public方法,接口是对外的承诺,承诺越少对系统的开发越有利,变更的风险也就越少,同时也有利于降低成本。
定制服务:系统设计时,需要考虑系统之间或模块之间的接口采用定制服务。只提供访问者需要的方法。
接口设计是有限度的:接口设计粒度越小,系统越灵活,结构越复杂,开发难度越大,可维护性越低。把握好”度“。
最佳实践:
一个接口只服务于一个子模块或业务逻辑;
通过业务逻辑压缩接口中的public方法
已被污染的接口,尽量去修改,若变更的风险较大,则采用适配器模式进行转化处理
实践、经验、领悟吧。
5. 迪米特法则(LoD, Law of Demeter)/最少知识原则(LKP, Least Knowledge Principle)
一个对象应该对其他对象有最少的了解。一个类应该对自己需要耦合或调用的类知道得最少,被耦合或调用的类的内部是如何复杂都与我我关,我只知道你提供的public方法,其他我一概不关心。
类内高内聚,类间低耦合。
LoD法则要求尽量“内敛”,尽量不要对外公布太多的public方法和非静态public变量,多使用private,package-private,protected等访问权限。
方法放在本类可以,放在其他类中也没有错,如何衡量?原则:如果一个方法放在本类中,不增加类间关系,也对本类不产生负面影响,就放置在本类中。
6.开闭原则(Open Closed Principle)
定义:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
理解:一个软件实体应该通过扩展来实现变化,而不是通过修改已有代码来实现变化。
开闭原则是最基础的一个原则,前面的五个原则都是开闭原则的具体形态。前五个原则就是指导设计的工具和方法,开闭原则才是精神领袖。
如何使用:
抽象约束:抽象是对一组事物的通用描述,没有具体的实现,也就表示它可以有非常多的可能性,可以跟随需求的变化而变化。
通过接口或抽象类约束扩展,对扩展进行边界限定,不允许出现在接口或抽象类中不存在的public方法
参数类型、引用对象尽量使用接口或抽象类,而不是实现类
抽象层尽量保持稳定,一旦确定即不允许修改
元数据控制模块行为:尽量使用配置参数来控制程序的行为,减少重复开发。如
Struts拦截器
Spring IoC
制定项目章程:约定优于配置
六大设计原则