设计模式分为3大类:
创建型模式(Creational Pattern)对类的实例化过程进行了抽象,能够将软件模块中对象的创建和对象的使用分离。为了使软件的结构更加清晰,外界对于这些对象只需要知道它们共同的接口,而不清楚其具体地实现细节,使整个系统的设计更加符合单一职责原则。
创建型模式在创建什么(What),由谁创建(Who),何时创建(When)等方面都为软件设计者提供了尽可能大的灵活性。创建型模式隐藏了类的实例的创建细节,通过隐藏对象如何被创建和组合在一起达到使整个系统独立的目的。
结构型模式(Structural Pattern)描述如何将类或者对 象结合在一起形成更大的结构,就像搭积木,可以通过 简单积木的组合形成复杂的、功能更为强大的结构。
结构型模式可以分为类结构型模式和对象结构型模式:
类结构型模式关心类的组合,由多个类可以组合成一个更大的 系统,在类结构型模式中一般只存在继承关系和实现关系。 - 对象结构型模式关心类与对象的组合,通过关联关系使得在一 个类中定义另一个类的实例对象,然后通过该对象调用其方法。 根据“合成复用原则”,在系统中尽量使用关联关系来替代继 承关系,因此大部分结构型模式都是对象结构型模式。
行为型模式(Behavioral Pattern)是对在不同的对象之间划分责任和算法的抽象化。
行为型模式不仅仅关注类和对象的结构,而且重点关注它们之间的相互作用。
通过行为型模式,可以更加清晰地划分类与对象的职责,并研究系统在运行时实例对象 之间的交互。在系统运行时,对象并不是孤立的,它们可以通过相互通信与协作完成某些复杂功能,一个对象在运行时也将影响到其他对象的运行。
行为型模式分为类行为型模式和对象行为型模式两种:
类行为型模式:类的行为型模式使用继承关系在几个类之间分配行为,类行为型模式主要通过多态等方式来分配父类与子类的职责。 对象行为型模式:对象的行为型模式则使用对象的聚合关联关系来分配行为,对象行为型模式主要是通过对象关联等方式来分配两个或多个类的职责。根据“合成复用原则”,系统中要尽量使用关联关系来取代继承关系,因此大部分行为型设计模式都属于对象行为型设计模式。
六大设计原则分别是单一职责原则、开闭原则、里式替换原则、接口隔离原则、依赖反转原则及迪米特原则。
单一职责原则意思是一个类只做一件事。也就是说,不要设计大而全的类,要设计粒度小、功能单一的类。
开闭原则是指对扩展开放,对修改关闭。具象来说,就是添加一个新的功能时,优先考虑在已有代码的基础上扩展代码,而非修改已有代码,这也要求我们要能写出扩展性好的代码。对扩展开放是为了应对变化(需求),对修改关闭是为了保证已有代码的稳定性,最终结果是为了让系统更有弹性。
里式替换原则是指子类对象能够替换程序中父类对象出现的任何地方,并且保证原来程序的逻辑行为不变以及正确性不会被破坏。听起来有点运行时多态的味道,但是里式替换作为一种设计原则,是用来指导继承关系中子类该如何设计的,子类的设计要保证在替换父类的时候,不改变原有程序的逻辑以及不破坏原有程序的正确性。一些常见的违背里式替换原则的例子有,子类的方法重写违背了父类声明要实现的功能、子类违背父类对输入/输出/异常的约定、子类违背父类注释中所罗列的任何特殊说明等。简单来说,就是子完美继承了父类的设计初衷,并做了增强。
接口隔离原则是指客户端不应该依赖于它不需要的接口。
依赖反转是指高层模块不要依赖于低层模块,它们应该通过抽象来相互依赖。除此之外,抽象不要依赖具体实现细节,具体实现细节依赖抽象。
依赖反转容易跟控制反转、依赖注入相混淆。控制反转是一个比较笼统的设计思想,并不是一种具体的实现方法,一般用来指导框架层面的设计。这里所说的控制指的是对程序执行流程的控制,而反转指的是在没有使用框架之前,程序员自己控制整个程序的执行。在使用框架之后,整个程序的执行流程通过框架来控制。流程的控制权从程序员反转给了框架。依赖注入是一种具体的编码技巧,我们不通过 new 的方式在类内部创建依赖类的对象,而是将依赖的类对象在外部创建好之后,通过构造函数、函数参数等方式注入给类来使用。
即最小知识原则。说的是,不该有直接依赖关系的类,不要有依赖;有依赖关系的类之间,尽量只依赖必要的接口。迪米特法则是希望减少类之间的耦合,让类越独立越好,每个类都应该少了解系统的其他部分,一旦发生变化,需要了解这一变化的类就会比较少。它和单一职责的目的都是实现高内聚低耦合,但是出发的角度不一样,单一职责是从自身提供的功能出发,迪米特法则是从关系出发。