设计模式是一套被反复使用、多数人只晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码,让代码更容易被他人理解、保证代码的可靠性。毫无疑问,设计模式于己于人于系统都是多赢的。设计模式使代码编制真正工程化,设计模式是软件工程的基石脉络,如同大厦结构一样。
单一职责原则
单一职责原则是最简单的面向对象设计原则,它用于控制类的粒度大小。其定义如下:
一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因
单一职责原则告诉我们:在软件系统中,一个类(大到模块,小到方法)承担的职责越多,它被复用的可能性越小,而且一个类承担的职责过多,就相当于将这些职责耦合在一起,当其中一个职责变化时,可能会影响其他职责的运作,因此要将这些职责进行分离,不同的职责封装在不同的类中,即将不同的变化原因封装在不同的类中,如果多个职责总是同时发生变化,则可以将他们封装在同一类中。
单一职责原则是实现“高内聚,低耦合”的指导方针,它是最简单但又最难应用的原则,需要设计人员发现类的不同职责并将其分离,而发现类的多重职责需要设计人员具有较强的分析设计能力和相关实践经验。
开闭原则
开闭原则是面向对象设计的终极目标,其概念如下:
一个软件实体如:类、模块和函数应该对扩展开发,对修改关闭。模块应尽量在不修改原来代码的情况下进行修改
在软件的生命周期内,因为变化、升级或者维护等原因需要对原有代码进行修改时,可能会给旧代码引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码进行重新测试。
在软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有代码来实现变化
注意事项:
-
通过接口或者抽象类约束扩展,对扩展进行边界界定,不允许出现接口或者抽象类不存在的public方法
-
参数类型,引用对象尽量使用接口或者抽象类,而不是实现类
-
抽象层尽量保持稳定,一旦确定即不允许修改。
优点:可复用性,可维护性
里氏替换原则
派生类(子类)对象能够替换其基类(父类)对象被调用,概念如下:
里氏替换原则(LSP)是面向对象设计的基本原则之一。里氏替换原则中说:任何出现基类的地方,子类一定可以出现。LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受影响,基类才能真正被复用,而衍生类也能够在基类的基础之上添加新的行为。里氏替换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏替换原则是对实现抽象化的具体步骤的规范。
当满足继承关系的时候,父类肯定是存在非私有的成员,子类肯定是得到了父类的非私有成员(假设父类的所有成员都是私有的,那么子类没有办法从父类继承任何成员,也就不存在继承的概念了)。既然子类继承了父类的这些非私有成员,那么父类对象也就可以在子类对象中调用这些非私有成员。所以,子类对象可以替换父类对象的位置。
需求变化时,只需继承,而别的东西不会改变。由于里氏替换原则在使得开放封闭成为可能。这使得子类可以在父类无需修改的情况下进行扩展。
依赖倒转原则
依赖倒转原则是程序要依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块的耦合。
有时候为了代码的复用,一般会把常用的代码写成函数或者类库。这样新开发项目时,直接用就行了。比如做大型项目时大多要访问数据库,所以我们就把访问数据的代码写成函数。每次做项目去调用这些函数。那么我们问题来了。我们要做新项目时,发现业务逻辑的高层模块都是一样的,但客户却希望使用不同的数据库或者存储方式,这时就出现麻烦了。我们希望再次利用这些高层模块,但发现高层模块与与低层的数据库访问是绑定在一起的,没法复用这些高层模块。所以不管是高层模块或者低层模块都应该依赖于具体抽象,具体一点就是接口或者抽象类,只要接口是稳定的,那么任何一个更改都不用担心。
高层不应该依赖于低层,两个都应该依赖于抽象;抽象不应该依赖于细节,细节依赖于抽象
接口隔离原则
客户端不应该依赖于它不需要的接口,类间的依赖关系应该建立在最小的接口上
接口隔离的核心定义是不出现臃肿的接口,但是小是有限度的,首先就是不能违反单一职责原则
合成/聚合复用原则
合成/聚合复用原则经常又叫做合成复用原则,其就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新的对象通过向这些对象的委派达到复用已有功能的目的。它的设计原则就是:要尽量使用合成/集合,尽量不要使用继承
聚合概念
聚合用来表示“拥有”关系或者整体与部分的关系。代表部分的对象有可能会被多个代表整体的对象所共享,而且不一定会随着某个代表整体的对象被销毁或破坏而被销毁或破坏,部分的生命周期可以超越整体。例如,Iphone5和IOS,当Iphone5删除后,IOS还能存在,IOS可以被Iphone6引用。
合成概念
合成用来表示一种强得多的“拥有”关系。在一个合成关系里,部分和整体的生命周期是一样的。一个合成的新对象完全拥有对其组成部分的支配权,包括它们的创建和湮灭等。使用程序语言的术语来说,合成而成的新对象对组成部分的内存分配、内存释放有绝对的责任。一个合成关系中的成分对象是不能与另一个合成关系共享的。一个成分对象在同一个时间内只能属于一个合成关系。如果一个合成关系湮灭了,那么所有的成分对象要么自己湮灭所有的成分对象(这种情况较为普遍)要么就得将这一责任交给别人(较为罕见)。例如:水和鱼的关系,当水没了,鱼也不可能独立存在。
迪米特法则
一个软件实体应当尽可能少的与其他实体发生相互作用。每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。迪米特法则的初衷在于降低类之间的耦合。由于每个类尽量减少对其他类的依赖,因此,很容易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系。迪米特法则不希望类之间建立直接的联系。如果真的有需要建立联系,也希望能通过它的友元类来转达。因此,应用迪米特法则有可能造成的一个后果就是:系统中存在大量的中介类,这些类之所以存在完全是为了传递类之间的相互调用关系——这在一定程度上增加了系统的复杂度。