并非一个原则。它包含:单一职责原则(SRP)、开闭原则(OCP)、里氏替换原则(LSP)、接口隔离原则(ISP)、依赖倒置原则(DIP)。其中,里氏替换和接口隔离这两个设计原则并不那么常用,稍微了解就可以了。我们重点学习了单一职责、开闭、依赖倒置这三个原则。
是类职责划分的重要参考依据,是保证代码”高内聚“的有效手段,是面向对象设计前两步(划分职责并识别出有哪些类、定义类及其属性和方法)的主要指导原则。单一职责原则的难点在于,对代码职责是否足够单一的判定。这要根据具体的场景来具体分析。同一个类的设计,在不同的场景下,对职责是否单一的判定,可能是不同的。
是保证代码可扩展性的重要指导原则,是对代码扩展性的具体解读。很多设计模式诞生的初衷都是为了提高代码的扩展性,都是以满足开闭原则为设计目的的。实际上,尽管开闭原则描述为对扩展开放、对修改关闭,但也并不是说杜绝一切代码修改,正确的理解是以最小化修改代价来完成新功能的添加。实际上,在平时的开发中,我们要时刻思考,目前的设计在以后应对新功能扩展的时候,是否能做到不需要大的代码修改(比如调整代码结构)就能完成。
主要用来指导框架层面的设计。高层模块不依赖低层模块,它们共同依赖同一个抽象。深挖一下的话,我们要把它跟控制反转、依赖注入、依赖注入框架做区分。实际上,比依赖倒置原则更加常用的是依赖注入。它用来指导如何编写可测试性代码,换句话说,编写可测试代码的诀窍就是应用依赖注入。
表示暂时不需要的就不要做。
表示要做就要尽量保持简单。
主要是提醒你不要写重复的代码。
又叫最小知道原则,不该有直接依赖关系的类之间,不要有依赖;有依赖关系的类之间,尽量只依赖必要的接口。
经典的设计模式有 23 种,分三种类型:创建型、结构型和行为型。其中,创建型设计模式主要解决“对象的创建”问题,结构型设计模式主要解决“类或对象的组合”问题,行为型设计模式主要解决“类或对象之间的交互”问题。
设计模式有很多种,常用的主要有:单例、工厂、建造者、代理、装饰器、适配器、观察者、模板、策略、职责链、迭代器这 11 种,所以,你只要集中精力,把这 11 种搞明白就可以了,剩下的那 12 种稍微了解,混个眼熟,等到真正用到的时候,再深入地去研究学习就可以了。
一个类只允许创建一个实例,经典实现模式懒汉式与饿汉式。
缺陷:扩展性不友好;可测试性不友好;不支持有参数的构造函数;
解决方案:工厂模式保证唯一性;
工厂模式用来创建不同但是相关类型的对象,继承同一父类或者接口的一组子类,由给定的参数来决定创建哪种类型的对象;
特点:封装对象的创建过程,将对象的创建和使用相分离;
简单工厂:对象创建逻辑简单,将多个对象的创建逻辑放到一个工厂类中;
工厂方法:当每个对象创建逻辑比较复杂时使用,将创建逻辑拆分得更细,每个对象的创建逻辑独立到各自的工厂类中;
抽象工厂:不常用;
作用4个:
实例:依赖注入框架 Spring IOC
用来创建复杂对象,定制化创建对象。
场景:创建不可变对象;
原型模式(节省创建时间)
深拷贝:完全独立的对象,更加耗时和内存空间;适用于可变对象;
浅拷贝:复制对象中基本类型的数据,引用对象的内存地址,不会递归复制引用对象及引用对象的引用对象;适用于不可变对象;
类或者对象组合在一起的经典结构,解决特定应用场景的问题;
不改变原始类接口的条件下,对原始类定义一个代理类,主要目的是控制访问而非加强功能(装饰器模式区别),代理类与原始类实现同样的接口,或者代理类继承原始类;
静态代理:事先针对每个类创建代理类,代理类代码重复;
动态代理:在运行时动态创建原始类对应的代理类,使用代理类动态替换原始类;
使用场景(非功能性需求):
监控、统计、鉴权、限流、事务、幂等、日志;缓存等;
将抽象(类库,骨架代码)和实现(类库)解耦,可以独立开发;
组合优于继承设计原则;
一种类之间的组合关系;
继承关系过于复杂,通过组合替代继承;
提供跟原始类不同的接口,将不兼容的接口转换为兼容的接口;用于事后补救前期的设计缺陷;
类适配器:继承关系实现
对象适配器:组合关系实现
场景:
解决类或对象之间的交互问题;
将观察者和被观察者代码解耦;邮件订阅
在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。
两大作用:复用和扩展。其中复用指的是,所有的子类可以复用父类中提供的模板方法的代码。扩展指的是,框架通过模板模式提供功能扩展点,让框架用户可以在不修改框架源码的情况下,基于扩展点定制化框架的功能。
定义一组算法类,将每个算法分别封装起来,让它们可以互相替换。策略模式可以使算法的变化独立于使用它们的客户端(这里的客户端代指使用算法的代码)。策略模式用来解耦策略的定义、创建、使用。实际上,一个完整的策略模式就是由这三个部分组成的。
多个处理器依次处理同一个请求。一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责,所以叫作职责链模式。
也叫游标模式,它用来遍历集合对象。
遍历集合一般有三种方式:for 循环、foreach 循环、迭代器遍历。后两种本质上属于一种,都可以看作迭代器遍历。
相对于 for 循环遍历,利用迭代器来遍历有 3 个优势:
迭代器模式封装集合内部的复杂数据结构,开发者不需要了解如何遍历,直接使用容器提供的迭代器即可;
迭代器模式将集合对象的遍历操作从集合类中拆分出来,放到迭代器类中,让两者的职责更加单一;
迭代器模式让添加新的遍历算法更加容易,更符合开闭原则。
除此之外,因为迭代器都实现自相同的接口,在开发中,基于接口而非实现编程,替换迭代器也变得更加容易。
一般用来实现状态机,而状态机常用在游戏、工作流引擎等系统开发中。状态机又叫有限状态机,它由 3 个部分组成:状态、事件、动作。其中,事件也称为转移条件。事件触发状态的转移及动作的执行。不过,动作不是必须的,也可能只转移状态,不执行任何动作。