设计模式原则
我们在开发的过程中,一般来说要求尽量做到代码的复用性和可维护性。代码的复用可以提高开发的效率和质量,避免重复造轮子,节约开发成本。如果代码的复用性做得好,系统的可维护性就会大大增强。在面向对象的开发中,我们进行代码设计时需要遵循设计模式的基本原则。遵循这些设计原则可以有效的提高系统的复用性、可扩展性和可维护性。
常用的设计原则包括:
单一职责原则:类的职责要单一,不能将太多的职责放在一个类中。
开闭原则:对扩展开放,对修改关闭。
里氏代换原则:父类出现的地方,子类一定也可以出现。
依赖倒置原则:要针对抽象编程,而非针对具体编程。即:依赖抽象,不依赖具体。
合成/聚合复用原则:系统中应该尽量使用组合和聚合关联关系,尽量少使用甚至不适用继承关系。
迪米特法则:一个软件实体对其它类的引用越少越好,或者说如果两个类彼此之间不直接通信,那么这两个类之间就不应当发生直接相互作用,而是通过引入一个第三者发生间接交互。
下面逐一讲解:
1. 单一职责原则(Single Responsibility Priciple, SRP)
定义:
一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中。(Every object should have a single responsibility, and that responsibility should be entirely encapsulated by the class.),即有且仅有一个原因使类变更。
简而言之:就是类的职责要单一,使类高内聚,低耦合。
2)类的职责主要包括两个方面:数据职责和行为职责,数据职责通过其属性来体现,而行为职责通过其方法来体现。
3)单一职责原则是实现高内聚、低耦合的指导方针,在很多代码重构手法中都能找到它的存在,它是最简单但又最难运用的原则,需要设计人员发现类的不同职责并将其分离,而发现类的多重职责需要设计人员具有较强的分析设计能力和相关重构经验。
2、提高类的可读性和维护性。
3、变更引起的风险减低,变更是必不可少的,如果接口的单一职责做得好,一个接口修改只对相应的类有影响,对其他接口无影响,这对系统的扩展性、维护性都有非常大的帮助。
1)当软件实体因需求要变化时, 尽量通过扩展已有软件实体,可以提供新的行为,以满足对软件的新的需求,而不是修改已有的代码,使变化中的软件有一定的适应性和灵活性 。已有软件模块,特别是最重要的抽象层模块不能再修改,这使变化中的软件系统有一定的稳定性和延续性。
2)实现开闭原则的关键就是抽象化:在"开-闭"原则中,不允许修改的是抽象的类或者接口,允许扩展的是具体的实现类,抽象类和接口在"开-闭"原则中扮演着极其重要的角色,即要预知可能变化的需求,又预见所有可能已知的扩展,所以在这里"抽象化"是关键!
3)可变性的封闭原则:找到系统的可变因素,将它封装起来。 这是对"开-闭"原则最好的实现。 不要把你的可变因素放在多个类中,或者散落在程序的各个角落.。你应该将可变的因素封套起来并且切忌不要把所用的可变因素封套在一起。
3. 里氏代换原则(Liskov Substitution Principle, LSP)
定义:
如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有变化,那么类型S是类型T的子类型。
以上的定义太过严格且难于理解,我们换一种说法:所有引用基类(父类)的地方必须能透明地使用其子类的对象。即子类能够必须能够替换基类能够从出现的地方。子类也能在基类的基础上新增行为。
简而言之:任何基类出现的地方,子类也可以出现。
原则分析:
3)子类可以形似父类,但又异于父类,“龙生龙,凤生凤,老鼠生来会打洞”是说子拥有父的“种”,“世界上没有两片完全相同的叶子”是指明子与父的不同;
4)提高代码的可扩展性,实现父类的方法就可以“为所欲为”了,君不见很多开源框架的扩展接口都是通过继承父类来完成的;
5)提高产品或项目的开放性。
2)降低代码的灵活性。子类必须拥有父类的属性和方法,让子类自由的世界中多了些约束;
3)增强了耦合性。当父类的常量、变量和方法被修改时,必需要考虑子类的修改,而且在缺乏规范的环境下,这种修改可能带来非常糟糕的结果——大片的代码需要重构。
高层模块不应该依赖低层模块,它们都应该依赖抽象。抽象不应该依赖于细节,细节应该依赖于抽象。简单的说,依赖倒置原则要求客户端依赖于抽象耦合。原则表述:
1)抽象不应当依赖于细节;细节应当依赖于抽象;
2)要针对接口编程,不针对实现编程。
原则分析:
1)如果说开闭原则是面向对象设计的目标,依赖倒转原则是到达面向设计"开闭"原则的手段。如果要达到最好的"开闭"原则,就要尽量的遵守依赖倒转原则。 可以说依赖倒转原则是对"抽象化"的最好规范!
2)依赖倒转原则的常用实现方式之一是在代码中使用抽象类,而将具体类放在配置文件中。
原则分析:
几种形式定义:
(1) 不要和“陌生人”说话。英文定义为:Don't talk to strangers.
(2) 只与你的直接朋友通信。英文定义为:Talk only to your immediatefriends.
(3) 每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。
简单地说,也就是,一个对象应当对其它对象有尽可能少的了解。一个类应该对自己需要耦合或调用的类知道得最少,你(被耦合或调用的类)的内部是如何复杂都和我没关系,那是你的事情,我就知道你提供的public方法,我就调用这么多,其他的一概不关心。