基于白嫖B站尚硅谷视频:尚硅谷Java设计模式(图解+框架源码剖析)
目录
- 1 写在前面
- 2 七大原则
- 3 UML类图
- 4 设计模式分类23种
- 5 单例模式
- 6 工厂模式(Factory Pattern)
- 7 原型模式(Prototype Pattern)
- 8 建造者模式(Builder Pattern)
- 9 适配器模式(Adapter Pattern)
- 10 桥接模式(Bridge)
- 11 装饰器模式(Decorator Pattern)
- 12 组合模式(Composite Pattern)
- 13 外观模式(Facade Pattern)
- 14 享元模式(Flyweight Pattern)
- 15 代理模式 (Proxy Pattern)
- 16 模版模式(Template Pattern)
- 17 命令模式(Command Pattern)
- 18 访问者模式(Visitor Pattern)
- 19 迭代器模式(Iterator Pattern)
- 20 观察者模式(Observer Pattern)
- 21 中介者模式(Mediator Pattern)
- 22 备忘录模式(Memento Pattern)
- 23 解释器模式(Interpreter Pattern)
- 24 状态模式(State Pattern)
- 25 策略模式(Strategy Pattern)
- 26 职责链模式(Chain of Responsibility Pattern)
1 写在前面
- 由Erich Gamma等人在1990年代由建筑设计领域引入到计算机科学领域;
- 七大原则;
- 23种设计模式;
- 高内聚,低耦合;
- 设计模式设计的七大原则;
2 七大原则
2.1 单一职责原则
2.1.1 基本介绍
对类来说,一个类只负责一项职责。
2.1.2 注意事项和细节
- 降低类复杂度,一个类只负责一项职责;
- 提高类的可读性,可维护性;
- 降低变更引起的风险;
2.2 接口隔离原则(Interface Segregation Principe)
- 客户端(实现接口的类)不应该依赖它不需要的接口方法;
- 接口尽量功能单一,尽量不要存在实现不全的情况(难度就在于命名);
2.3 依赖倒转(倒置)原则(Dependence Inversion Principe)
2.3.1 基本介绍
- 高层模块不应该依赖底层模块,二者都应该依赖其抽象(抽象类、接口);
- 中心思想:面向接口编程;
2.3.2 例子
背景:人类(class Person)接受邮件类(class Email),传统方法,人类中实现一个Email对象。
问题:要是邮件变成微信、短信。。。又要改动人类。
解决:定义一个接口,接口定义了抽象方法(接受),人类的方法里面实现接口作为形参,其他的要接受的对象实现这个接口。
2.3.3 依赖关系实现方法
- 通过接口实现;
- 通过构造方法;
- 通过setter方法;
2.4 里氏替换原则
实际上是在讲继承的注意点,即如何正确使用继承;
- 原则:父类引用能够透明使用子类对象;
- 实现继承时,子类尽量不要重写(overwrite)父类方法;
- 若错怎么改进:继承同一个更基础类,通过组合、聚合、依赖实现二者关系。
2.5 开闭原则(open closed Principe)
- 原则:对扩展(制作方)开放,对修改(使用方)关闭;尽量扩展,而不是修改;
- 开闭原则是核心;
- 使用方只接受接口形参,制作方实现接口;
2.6 迪米特法则(Demeter Principe)
- 原则:一个对象应该对其他对象保持最少的了解;
- 类与类之间关系越密切,耦合度就越大;
- 迪米特法则又叫最小知道原则,要对自己依赖的类知道的越少越好,
- 只与直接朋友进行通信:成员变量、方法参数、方法返回值;
- 和依赖类直接的关系不要使用局部变量来实现,尽量使用直接朋友;
- 注意特米特法则是降低两个类之间的耦合,不是消除!
2.7 合成复用原则
类间关系尽量使用合成/聚合的方式,而不是继承;
3 UML类图
3.1 实体
- 类(class)
- 接口(interface)
3.2 关系
- 依赖(Dependency):如果在类A中用到了类B,就是存在依赖关系;
- 关联(Association):有导航性的依赖关系;
- 泛化(Generalizaton):其实就是继承关系,extends;
- 实现(Realization):其实就是实现接口,implements;
- 聚合(Aggregation):整体和部分的关系,整体和部分是可以分开的,具有导航性。如电脑和键盘、显示器、鼠标的关系,可以分离开。生命周期不同。实现可以是该对象成员变量引用其他对象;
- 组合(Composite):如果生命周期一致,那么就是组合关系;共同消亡;实现方式可以是成员变量new一个进行初始化;
4 设计模式分类23种
- 创建型模式:单例模式、抽象工厂模式、原型模式、建造者模式、工厂模式;
- 结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式;
- 行为型模式:模板方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式。
5 单例模式
5.1 介绍
一个类只能存在一个对象实例;
5.2 写法
要求:懒加载、线程安全。
- 饿汉式(静态常量)
- 饿汉式(静态代码块)
- 懒汉式(线程不安全)
- 懒汉式(线程安全,同步方法)
- 懒汉式(线程安全,同步代码块)
- 双重检查
- 静态内部类
- 枚举
6 工厂模式(Factory Pattern)
6.1 简单工厂模式
由一种工厂对象决定创建出哪一种产品类的实例。把需要创建一批类似的对象的任务交给工厂对象去完成,需要特定对象的时候只用改工厂对象代码,其他位置不用改。
比如父类是一个披萨类,然后各自披萨子类继承父类,定义一个披萨生产工厂类,创建实例对象,根据不同的定制要求作为参数给工厂,工厂返回一个定制的披萨。
6.2 工厂方法模式
把创建对象的方法抽象成方法,由子类工厂决定要实例化成什么样子。
6.3 抽象工厂模式
创建一个工厂接口,包含生产对象的抽象方法(超级工厂)。具体的实现由具体的工厂去完成,
7 原型模式(Prototype Pattern)
是用于创建重复的对象,同时又能保证性能,用原型对象实力指定创建对象的种类,并通过拷贝这些原型,创建新的对象。
7.1 通过clone()深拷贝
stu = (Student) super.clone();//先处理基础数据类型和String类型
stu.address= (Address) stu.address.clone();//再处理对象类型
7.2 通过对象序列化实现深拷贝
……待深挖。
8 建造者模式(Builder Pattern)
使用多个简单的对象一步一步构建成一个复杂的对象。将产品和产品建造过程进行解耦。
四个核心角色:
- 产品角色(product):具体产品对象;
- 抽象建造者(Builder):生产产品的抽象类(或者接口);
- 具体建造者(ConcreteBuilder):实现接口,构建和装配部件;
- 指挥者(Director):使用Builder的对象。
jdk源码的StringBuilder就是采用了建造者模式。
9 适配器模式(Adapter Pattern)
作为两个不兼容的接口之间的桥梁。
9.1 类适配器
被适配器(插座)类:输出220V方法。
适配器接口:输出5V方法。
适配器:继承被适配器类,同时实现适配器接口,获得被适配器的输出220V,实现接口方法转成5V,输出正确的电压。
9.2 对象适配器
将被适配器对象聚合到适配器中,实现适配器接口,输出正确的电压。
9.3 接口适配器
适用于一个接口不想使用其所有的方法的情况。
注意:抽象类可以没有抽象方法。
接口适配器实现部分不需要的接口(直接空实现{}无执行代码)。
10 桥接模式(Bridge)
是用于把抽象化与实现化解耦,使得二者可以独立变化。
把接口作为一个抽象类的关联(组合,聚合),实现具体的类只完成抽象类的方法,相当于把这个接口作为了一个桥。相当于乘法(解决继承指数爆炸问题)。
JDBC使用了桥接模式。
11 装饰器模式(Decorator Pattern)
允许向一个现有的对象添加新的功能,同时又不改变其结构。
四个角色:
- 主体抽象接口:需要被装饰的主体。(抽象接口父类)例如:咖啡的父类饮料。
- 主体:主体抽象的一个实现。例如:咖啡。
- 抽象装饰类(核心):包含了主体抽象接口引用(聚合),同时实现了主体抽象接口。相当于即是主体,又含有基础主体的引用(方便累加)。例如:加调料的饮料抽象类
- 装饰类:实现了抽象装饰类。例如,加糖的饮料,加奶的饮料。
注意:客户端使用的时候是用对象去初始化装饰的对象。
*知识点很多,值得细品。
java I/O流使用了装饰者模式。
12 组合模式(Composite Pattern)
又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。
适用于树形结构,都来继承自同一个抽象类,嵌套输出。
jdk中集合类Hashmap采用这种方式。
13 外观模式(Facade Pattern)
隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。
在MyBatis用到了外观模式。
非常简单,就是聚合到一起。
14 享元模式(Flyweight Pattern)
主要用于减少创建对象的数量,以减少内存占用和提高性能。
三种元素:
- 实体父类(抽象类、接口):抽象一个实体;
- 实体类:实现了实体父类;
- 实体父类工厂类:里面存放着实体,要是有直接返回,没有就加入进去;
jdk中String常量池、数据库连接池、Integer、缓冲池等等。
15 代理模式 (Proxy Pattern)
一个类代表另一个类的功能。
15.1 静态代理
代理对象和目标对象都要实现相同的接口,然后通过调用相同的方法来调用目标对象的方法。
核心:代理对象实现接口同时聚合目标对象(和装饰器模式一样)。
15.2 动态代理(JDK代理、接口代理)
需要先理解反射,才能理解动态代理。
15.3 Cglib代理
可以不实现接口。
需要额外的jar包:asm、asm-commons、asm-tree、cglib-2.2
16 模版模式(Template Pattern)
一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。
**实质上是典型的抽象类定义模板、实现类实现抽象类的行为性设计模式的例子。**注意不是接口。
Spring IOC用到了模板模式。
17 命令模式(Command Pattern)
是一种数据驱动的设计模式,它属于行为型模式。
角色:
- Invoker(命令发布者):聚合Command;
- Receiver(命令接收者):命令的执行体;
- Command(命令接口):命令执行从抽象方法;
- myCommand(命令实现):聚合Receiver;
理解:相当于在命令发送者和命令执行者直接添加了一个命令实体,发送者不直接控制执行者,而是控制命令,命令再控制执行,这样可以利用队列进行不断执行。
在Spring框架jdbcTemplate里面使用了命令模式。
18 访问者模式(Visitor Pattern)
角色:
- 被访问者:要实现被访问的方法accept(Visitor visitor),方法体里面把自己传入进去visitor.visit(this)。
- 访问者:实现Visitor接口,实现visit方法,根据不同的访问者身份编写自己的逻辑。
核心:数据在被访问者哪里,数据操作在访问者哪里。实现数据结构和数据操作的分离。
19 迭代器模式(Iterator Pattern)
这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。
interface Iterator{
public abstract boolean hasNext();//判断是否还有下一个
public abstract Object next();//返回下一个
}
都实现这样的接口,按照这样的方式进行迭代的元素访问,指针index往后。
JDK的ArrayList用到了迭代器模式。
20 观察者模式(Observer Pattern)
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。
角色:
- 观察者:有一个更新的方法。
- 服务端:保存数个观察者 ,可以注册、删除、通知观察者,当有更新就通知所有的观察者。
jdk中的Observable类使用了观察者模式。
21 中介者模式(Mediator Pattern)
中介者模式是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。
让一个中介者在各个对象之间游走,而不是类之间有依赖。
22 备忘录模式(Memento Pattern)
保存一个对象的某个状态,以便在适当的时候恢复对象。
最重要的功能:存档!
角色:
- 状态类:需要存档的状态;
- 实体:需要实现一个返回状态的方法,和加载状态的方法。
- 状态仓库:用来保存一些状态。
23 解释器模式(Interpreter Pattern)
解释器模式提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。
待细挖。
24 状态模式(State Pattern)
在状态模式中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。
针对一个项目,要准备一个状态流程图,其中点表示状态,边表示行为。
角色:
- 状态父类(接口、抽象类):里面包含了所有行为方法。
- 状态实现:每一种状态都实现了具体的方法,只是实现方法不一样而已。
- 状态拥有者类:维护一个状态变量,设置set和get状态的方法。
25 策略模式(Strategy Pattern)
理解:就是把策略抽象成父类,不同子类实现其不同的方法,策略使用者直接使用策略父类,具体实现对其隐藏,好处在于这个具体策略是可以动态改变的。
jdk中Arrays使用了策略模式。
26 职责链模式(Chain of Responsibility Pattern)
顾名思义,责任链模式为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。
用链表结构来理解。
角色:
- 事务处理者父类(抽象类):包含一个自己的信息,以及下一事物参与者的聚合。
- 事务处理者:实现父类。注意要实现逻辑,如果自己不能处理就交给下一个事务处理者。
- 事务:需要处理的事务。