设计模式的六大设计原则
1、开闭原则(OCP)
概念:软件实体应当对扩展开放,对修改关闭(Software entities should be open for extension,but closed for modification),即:一个软件实体应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化。
软件实体:①项目中划分出的模块;②类与接口;③方法
可以通过创建子类的方式,重写原有的需要修改的方法,该子类本质就是创建一个扩展来扩展原有的功能,重写后可以通过调用重写后的方法来实现新增功能的使用。
作用:
① 便于软件测试,在软件测试中使用该原则,可以防止更改时出现问题;
② 可以提高代码的可复用性,原有的代码如果在接口和实现类中进行更改,会导致更改量过大,不如重新写该代码,而采用开闭原则增加扩展类,让原有的功能依然可以实现,可以增强代码的复用性,让代码的功能依旧可以实现;
③ 可以提高软件的可维护性
2、单一职责原则(SRP)
概念:单一职责原则又称单一功能原则,、这里的职责是指类变化的原因,单一职责原则规定一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分。
单一职责原则的核心就是控制类的粒度大小、将对象解耦、提高其内聚性。
作用:
① 降低类的复杂度。
② 提高类的可读性。
③ 提高系统的可维护性。
④ 变更引起的风险降低。
单一职责原则根据不同人在不同项目中对其进行功能的划分会有变化,每个人在对项目职责及功能的思考时会有不同的设定,所以该原则在不同项目中的设定会有差别。
3、里氏替换原则(LSP)
概念:在一个程序中,如果可以将一个类T的对象全部替换为另一个类S的对象,而程序的行为没有发生变化,那么S是T的子类;任何一个使用父类的地方,都可以把它替换成它的子类,而不会发生任何错误或异常,但有子类出现的地方,父类未必可以替换;所有的引用基类的地方必须能透明地使用其子类对象。
定义中的含义:
①子类必须完全实现父类的方法。
②子类中可以增加自己特有的方法。
③当子类覆盖或实现父类的方法时,方法的输入参数(方法的形参)要比父类方法的输入参数更宽松。
④ 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
作用:
① 里氏替换原则是实现开闭原则的重要方式之一。
② 它克服了继承中重写父类造成的可复用性变差的缺点。
③ 它是动作正确性的保证。即类的扩展不会给已有的系统引入新的错误,降低了代码出错的可能性。
4、依赖倒置原则(DIP)
定义:每个类尽量提供接口或抽象类,或者两者都具备; 变量的声明类型尽量是接口或者是抽象类;任何类都不应该从具体类派生;尽量不要覆写基类的方法;使用继承时结合里氏替换原则。
高层模块面向了接口或抽象类,在后续的对项目内容进行增加时就会更加利于添加模块,而不会造成冲突和代码大量更改。
举个栗子:当我们需要为一个类的构造方法传入一个人的参数时,这个人可能是老师、学生、工人或者宇航员,而我们不能为每一个参数创建一个构造方法,所以我们为这些参数统一构建一个抽象方法(人),我们在传入参数时传入人这个参数,根据里氏替换原则我们可以知道,子类可以替代父类,所以我们只需要书写一个构造方法就可以替代n种构造方法。而且我们也可以在不更改类的基础上为内容进行添加,满足了开闭原则。
作用:
①依赖倒置原则可以降低类间的耦合性。
②依赖倒置原则可以提高系统的稳定性。
③依赖倒置原则可以减少并行开发引起的风险。
④依赖倒置原则可以提高代码的可读性和可维护性。
5、接口隔离原则(ISP)
定义:客户端不应该被迫依赖于它不使用的方法;一个类对另一个类的依赖应该建立在最小的接口上。即:要为各个类建立它们需要的专用接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。
作用:
①将臃肿庞大的接口分解为多个粒度小的接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。
② 接口隔离提高了系统的内聚性,减少了对外交互,降低了系统的耦合性。
③ 如果接口的粒度大小定义合理,能够保证系统的稳定性;但是,如果定义过小,则会造成接口数量过多,使设计复杂化;如果定义太大,灵活性降低,无法提供定制服务,给整体项目带来无法预料的风险。
④ 使用多个专门的接口还能够体现对象的层次,因为可以通过接口的继承,实现对总接口的定义。
⑤ 能减少项目工程中的代码冗余。过大的大接口里面通常放置许多不用的方法,当实现这个接口的时候,被迫设计冗余的代码。
实现方法:
①接口尽量小,但是要有限度。一个接口只服务于一个子模块或业务逻辑。
②为依赖接口的类定制服务。只提供调用者需要的方法,屏蔽不需要的方法。
③了解环境,拒绝盲从。每个项目或产品都有选定的环境因素,环境不同,接口拆分的标准就不同深入了解业务逻辑。
④提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。
6、迪米特法则(LoD)
定义:又叫作最少知识原则,要求一个对象应该对其他对象有最少的了解;即:如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。
作用:
① 降低了类之间的耦合度,提高了模块的相对独立性。
② 由于亲合度降低,从而提高了类的可复用率和系统的扩展性。
迪米特法则不可过度使用,过度使用迪米特法则会使系统产生大量的中介类,增加系统的复杂性使模块间通讯效率降低。
要求:
① 在类的划分上,应该创建弱耦合的类。类与类之间的耦合越弱,就越有利于实现可复用的目标。
② 在类的结构设计上,尽量降低类成员的访问权限。
③ 在类的设计上,优先考虑将一个类设置成不变类。
④ 在对其他类的引用上,将引用其他对象的次数降到最低。
⑤ 不暴露类的属性成员,而应该提供相应的访问器(set 和 get 方法)。
⑥ 谨慎使用序列化(Serializable)功能。
总结
设计模式的六大原则使我们在编写代码时需要考虑的,当我们考虑这六大原则时,我们的代码就会变得更加简洁直观明了,让我们在编写过程中出现的问题变少。
同时这六大原则也是我们所有的设计模式所采用的原则,不同的设计模式虽然有一些偏向,但是总体都是遵循着这六大原则。