赞
踩
目录
对于面向对象的软件系统,在支持可维护性的同时,提高系统的复用性是一个很重要的问题。在面向对象的设计当中,可维护性是以设计原则为基础的。面向对象的原则包括七种。
单一职责原则(SRP)Single Responsibility Principle
一个类只负责一个功能另有中的相应职责----------就一个类而言,应该只有一个引起它变化的原因;
也就是说一个类里最好是放一种类型的方法;比如:
DAO:只放操作数据库的方法;
Util:只放某个工具的方法;
……………………
单一职责原则:实现高内聚,低耦合;
开闭原则(OCP)------Open-Closed Principle:消灭分支语句 if...else...
软件的实体应该对拓展开放,对内修改关闭。
即:当有新的需求的时候,我们不用修改现在的代码,只需要添加新的代码就可以;
关键:抽象化,并从抽象化导出具体实现;
里氏代换原则(LSP)--------Liskov Substitution Prinicple
所有引用其父类的地方都能够透明的引用其子类;
不应该在代码中出现if/else之类对派生类类型进行判断的条件;
○ 派生类应当可以替换基类,并出现在基类能够出现的任何地方,或者说如果我们把代码中使用基类的地方用它的派生类所代替,代码还能正常工作;
里氏替换原则是使代码符合开闭原则的一个重要保证;
● 具体来说:子类可以扩展父类的功能,但不能改变父类原有的功能
○ 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法;
○ 子类可以增加自己特有的方法;
○ 当子类单独的方法重载父类的方法时,方法的前置条件(即方法的输入/入参)要比父类方法的输入参数更宽松;
○ 当子类的方法实现父类的方法时(重载/重写或实现抽象方法)的后置条件(即方法的输出/返回值)要比父类更严格或者相等;
里氏替换原则的优点:
● 约束继承泛滥,是开闭原则的一种体现;
● 加强程序的健壮性,同时变更时也可以做到非常好的提高程序的维护性、扩展性。降低需求变更时引入的风险;
重构违反LSP的设计:
如果两个具体的类A,B之间的关系违反了LSP,(假如是从B到A的继承关系),那么根据具体的情况可以在下面的两种重构方案中选择一种:
● 创建一个新的抽象类C,作为两个具体类的基类,将A,B的共同行为移动到C中来解决问题。
● 从B到A的继承关系改为关联关系;
依赖倒置原则(DIP)------Dependece Inversion Principle
抽象不应该不依赖于细节,细节应该依赖于抽象;
即:针对接口编程,而不是针对实现编程。
A. 高层模块不应该依赖于低层模块,二者都应该依赖于抽象
B. 抽象不应该依赖于细节,细节应该依赖于抽象
C.针对接口编程,不要针对实现编程。
依赖:在程序设计中,如果一个模块a使用或者调用了另一个模块b,那么就是模块a依赖模块b;
高层模块与底层模块:在一个应用程序中,我们有一些低层次的类,这些类实现了一些基本的或者初级的操作,我们称之为低层模块;另外有一些高层次的类,这些类封装了某些复杂的逻辑,并且依赖于低层次的类,这些类我们称之为高层模块;
依赖倒置:面向对对象程序设计相对于面向过程(结构化)程序设计而言,依赖关系被倒置了。因为传统的结构化程序设计中,高层模块总是依赖于低层模块。
一个良好的设计应该是系统的每一部分都是可替换的。如果高层模块过分依赖低层模块,一方面一旦底层模块需要替换或者修改,高层模块将受到影响;另一方面,高层模块很难可以重用;
解决方案:在高层模块和低层模块之间,引入一个抽象接口层。
高层---->抽象接口层---->低层
High level Policy -------->Abstract Interface--------->Detailed Implementation
抽象接口是对低层模块的抽象,低层模块继承或者实现该抽象接口;
这样,高层模块不直接依赖低层模块,而是依赖抽象接口层。抽象接口也不依赖低层模块的实现细节,而是低层模块依赖(继承或者实现)抽象接口;
类和类之间都通过抽象接口层来建立关系。
怎么使用依赖倒置原则:
1、依赖于抽象
● 任何变量都不应该持有一个指向具体类的指针或引用。
● 任何类都不应该从具体类派生
2、设计接口而非设计实现
● 使用继承避免对类的直接绑定
● 抽象类/接口:倾向于较少的变化;抽象是关键点,它易于修改和扩展;不要强制修改那些抽象类或者接口;
3、避免依赖的传递
● 避免高层依赖于低层
● 使用继承和抽象类来有效的消除传递依赖
依赖倒置原则的优点:
可以减少类间的耦合性、提高系统的稳定性,提高代码可读性和可维护性,可降低修改程序所造成的的风险。
接口隔离原则(ISP)Interface Segregation Principle
不能强迫用户去依赖那些他们不使用的接口。即:使用多个专门的接口会比使用单一的总接口好;
● 接口的设计原则:接口的设计应该遵循最小接口原则,不要把用户不使用的方法也塞到同一个接口里面;如果一个接口的方法没有被使用到,这说明应该将其分割成几个功能转移的接口;
● 如果一个接口a继承另一个接口b,则接口a相当于继承了接口b的方法,那么继承了接口b之后,接口a也应该遵循上述原则:不应该包含用户不使用的方法。繁殖,则说明接口a被接口b污染了,应该重新设计关系;
接口分隔原则:
1、一个类对一个类的依赖应该建立在最小的接口上
2、建立单一接口,不要建立庞大臃肿的接口
3、尽量细化接口,接口中的方法尽量少
合成复用原则(CARP)----Composite/Aggregate Reuse Principle
尽量使用对象组合,而不是继承来达到复用的目的;
相对于继承复用而言,其耦合性相对较低,成员对象对新对象影响不大。可动态运行。复用时尽量减少组合/聚合关系,少用继承;
合成复用原则优缺点:
优点:
● 新对象存取子对象的唯一方法是通过子对象的接口。
● 这种复用是黑箱复用,因为子对象的内部细节是新对象所看不见的。
● 这种复用更好地支持封装性。
● 这种复用实现上的相互依赖性比较小。
● 每一个新的类可以将焦点集中在一个任务上。
● 这种复用可以在运行时间内动态进行,新对象可以动态的引用与子对象类型相同的对象。
● 作为复用手段可以应用到几乎任何环境中去。
缺点:
系统中会有较多的对象需要管理。
通过继承来实现复用的优缺点:
优点:
● 新的实现较为容易,因为基类等等大部分功能可以通过继承的关系自动进入派生类;
● 修改和扩展继承而来的实现较为容易;
缺点:
● 继承复用破坏封装性,继承将基类的实现细节暴露给派生类。由于基类的内部细节常常是对于派生类透明的,所有这种复用是透明的复用,又称“白箱”复用;
● 如果基类发生改变,那么派生类的实现不得不发生改变;
● 从基类继承而来的实现是静态的,不可能在运行时间内发生改变,没有足够的灵活性。
迪米特法则(LoD)------Law of Demeter
又叫做最少知道原则(Least Knowledge Principle)
一个软件实体应当尽可能少的与其他实体发生相互作用;
每一个软件单位对其他的单位都只有最少的只是,而且局限于那些本单位密切相关的软件的单位;
例如:
购房者要购买楼盘A、B、C中的楼,他不必直接到楼盘去买楼,而是可以通过一个售楼处去
了解情况,这样就减少了购房者与楼盘之间的耦合。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。