###设计模式概述 在软件工程中,设计模式(Design Pattern)是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案。这个术语是由埃里希·伽玛(Erich Gamma)等人在1990年代从建筑设计领域引入到计算机科学的。 设计模式并不直接用来完成代码的编写,而是描述在各种不同情况下,要怎么解决问题的一种方案。面向对象设计模式通常以类或对象来描述其中的关系和相互作用,但不涉及用来完成应用程序的特定类或对象。设计模式能使不稳定依赖于相对稳定、具体依赖于相对抽象,避免会引起麻烦的紧耦合,以增强软件设计面对并适应变化的能力。 并非所有的软件模式都是设计模式,设计模式特指软件“设计”层次上的问题。还有其它非设计模式的模式,如架构模式。同时,算法不能算是一种设计模式,因为算法主要是用来解决计算上的问题,而非设计上的问题。 ###设计模式六大原则 ####单一职责原则 - 一个类或者一个方法只负责一项职责,尽量做到类的只有一个行为原因引起变化。 ####里氏替换原则 - 如果对每个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型。 - 换句话说,所有引用基类的地方必须能透明地使用其子类的对象。 - 由定义可知,在使用继承时,遵循里氏替换原则,在子类中尽量不要重写和重载父类的方法。 - 继承包含这样一层含义:父类中凡是已经实现好的方法(相对抽象方法而言),实际上是在设定一系列的规范和契约,虽然它不强制要求所有的子类必须遵循这些契约,但是如果子类对这些非抽象方法任意修改,就会对整个继承体系造成破坏。而里氏替换原则就是表达了这一层含义。 ####依赖倒置原则 - 高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。 - 类A直接依赖类B,如果要将类A改为依赖类C,则必须通过修改类A的代码来达成。此时,类A一般是高层模块,负责复杂的业务逻辑,类B和类C是低层模块,负责基本的原子操作;修改A会给程序带来风险。 - 将类A修改未依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或类C发生联系,则会大大降低修改类A的记几率。 - 依赖倒置原则基于这样一个事实:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。 ####接口隔离原则 - 客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。 - 类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类C来说不是最小接口,则类B和类D必须去实现他们不需要的方法。 - 将臃肿的接口I拆分为独立的几个接口,类A和类C分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则。  >这个图的意思是:类A依赖接口I中的方法1,方法2,方法3,类B是对类A依赖的实现;类C依赖接口I中的方法1,方法4,方法5,类D是对类C依赖的实现。对于类B和类D来说,虽然存在用不到的方法(红色标记所示),但由于实现了接口I,所以也必须要实现这些用不到的方法。 ####迪米特法则 - 一个对象应当对其他对象有尽可能少地了解,简称类间解耦. - 一个类尽量减少自己对其他对象的依赖,原则是低耦合,高内聚,只有使各个模块之间的耦合尽量的低,才能提高代码的复用率。 ####开放封闭原则 - 软件实体(如类、模块、函数等)应该对拓展开放,对修改关闭。 - 在增加一个功能时,应当尽可能地不去改动已有的代码;当修改一个模块时不应该影响到其他的模块。 ###代码重构 - 不是对已有代码的全盘否定,而是对不合理的结构进行调整,合理的模块进行改动;利用更好的方式,写出更好,更有维护性代码。 ###为什么重构 - 重复的代码太多,没有复用性;难于维护,需要修改时处处都得改。 - 代码的结构混乱,注释也不清晰;没有人能清楚地理解这段代码的含义。 - 程序没有拓展性,遇到新的变化,不能灵活的处理。 - 对象结构强耦合,业务逻辑太复杂,牵一发而动全身,维护时排查问题非常困难。 - 部分模块性能低,随着用户的增长,已无法满足响应速度的要求。 ###重构的时机 - 添加功能时 - 修补错误时 - 复审代码时 ###如何重构 - 重命名 - 函数重构 - 提炼函数 - 去除不必要的参数 - 用对象取代参数 - 隐藏函数