设计模式
设计模式通常分为三大类:创建型模式、结构型模式和行为型模式。
创建型模式(Creational Pattern):对类的实例化过程进行了抽象,能够将软件模块中对象的创建和对象的使用分离。共有5种,包括工厂方法模式、抽象工厂模式、单例模式、建造者模式和原型模式。
结构型模式(Structural Pattern):关注于对象的组成以及对象之间的依赖关系,描述如何将类或者对象结合在一起形成更大的结构。共有7种,包括适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式和享元模式。
行为型模式(Behavioral Pattern):关注于对象的行为问题,是对在不同的对象之间划分责任和算法的抽象化。共有11种,包括策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式和解释器模式1。
# 创建型模式
# 工厂方法模式
- 创建型模式
- 避免创建者与具体的产品逻辑耦合
- 满足单一职责,每一个业务逻辑实现都在所属自己的类中完成
- 满足开闭原则,无需更改使用调用方就可以在程序中引入新的产品类型
# 实战抽象工厂模式
- 创建型模式
- 抽象工厂是一个中心工厂,创建其他工厂的模式。
- 抽象工厂模式,所要解决的问题就是在一个产品族,存在多个不同类型的产品(Redis集群、操作系统)情况下,接口选择的问题。
# 原型模式
- 创建者模式
- 上机考试多套试,每人题目和答案乱序排列场景
- 原型模式主要解决的问题就是创建大量重复的类
# 单例模式
- 创建型模式
- 数据库的连接池不会反复创建
- spring中一个单例模式bean的生成和使用
- 在我们平常的代码中需要设置全局的的一些属性保存
# 七种单例模式
1、 懒汉模式(线程不安全)
public class Singleton_01 {
private static Singleton_01 instance;
private Singleton_01() {
}
public static Singleton_01 getInstance() {
if (null != instance) {
return instance;
}
instance = new Singleton_01();
return instance;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
- 单例模式有一个特点就是不允许外部直接创建,也就是
new Singleton_01()
,因此构造函数上添加私有属性private
。 - 此种单例满足懒加载,但是不是线程安全的
2、懒汉模式(线程安全)
public class Singleton_02 {
private static Singleton_02 instance;
private Singleton_02() {
}
public static Synchronized Singleton_02 getInstance() {
if (null != instance) return instance;
instance = new Singleton_02();
return instance;
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- 这种模式虽然安全,但由于把锁加到方法上后,所有的访问都因需要锁导致资源的浪费
3、饿汉模式(线程安全)
public class Singleton_03 {
private static Singleton_03 instance = new Singleton_03();
private Singleton_03() {
}
public static Singleton_03 getInstance() {
return instance;
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- 程序启动之处就会创建该对象
- 可能加载没必要的实例对象,加大内存的压力
4、使用类的内部类(线程安全)
public class Singleton_04 {
private static class SingletonHolder {
private static Singleton_04 instance = new Singleton_04;
}
private Singleton_04() {
}
private static Singleton_04 getInstance() {
return SingletonHolder.instance;
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- 使用类的静态内部类实现的单例模式,既保证了线程安全,又保证了懒加载,同时不会因为加锁的方式耗费性能
- 类加载机制保证在任何线程中,一个类只会被加载一次,所以这个静态内部类只会被初始化一次,类加载机制线程安全
5、双重锁校验(线程安全)、
public class Singleton_05 {
private static volatile Singleton_05 instance;
private Singleton__05() {
}
public static Singleton_05 getInstance() {
if (null != instance) return instance;
synchronized (this.class) {
if (null == instance) {
instance = new Singleton_05();
}
}
return instance;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- synchronized 关键字保证同一时间只有一个线程可以进入
synchronized
的代码块 - 使用
volatile
关键字修饰是为了防止指令重排,创建对象不是原子操作,如果不防止指令重排的话,可能导致其他线程获取到一个未初始化完成的对象
6、CAS(AtomicReference)线程安全
public class Singleton_06 {
private static final AtomicReference<Singleton_06> INSTANCE = new AtomicReference<Singleton_06>();
private Singleton_06() {
}
public static final Singleton_06 getInstance() {
for ( ; ; ) {
Singleton_06 instance = INSTANCE.get();
if (null != instance) {
return instance;
}
INSTANCE.compareAndSet(null, new Singleton_06());
return INSTANCE.get();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- AtomicReference原子操作保证同一时间只能有一个线程能设置值成功
7、枚举单例(线程安全)
public enum Singleton_07 {
INSTANCE;
}
1
2
3
2
3
- 简洁,线程安全,自由串行化,单一实例
# 结构型模式
# 适配器模式
- 从多个MQ消息体中,抽取指定字段值场景
- 适配器模式的主要作用就是把原本不兼容的接口,通过适配修改做到统一。使得用户方便使用,就像我们提到的万能充、数据线、MAC笔记本的转换头、出国旅游买个插座等等,他们都是为了适配各种不同的口,做的兼容。
# 桥接模式
- 多支付渠道(微信、支付宝)与多支付模式(刷脸、指纹)场景
- 桥接模式的主要作用就是通过将抽象部分与实现部分分离,把多种可匹配的使用进行组合。说白了核心实现也就是在A类中含有B类接口,通过构造函数传递B类的实现,这个B类就是设计的桥。
- JDBC多种驱动程序的实现、同品牌类型的台式机和笔记本平板、业务实现中的多类接口同组过滤服务等。这些场景都比较适合使用桥接模式进行实现,因为在一些组合中如果每一个类都实现不同的服务可能会出现笛卡尔积,而使用桥接模式就可以非常简单。
# 组合模式
- 营销差异化人群发券,决策树引擎
- 组合模式的主要解决的是一系列简单逻辑节点或者扩展的复杂逻辑节点在不同结构的组织下,对于外部的调用是仍然可以非常简单的。
# 装饰器模式
- SSO单点登录功能扩展,增加拦截用户访问方法范围场景。
- 装饰器的核心就是再不改原有类的基础上给类新增功能。
new BufferedReader(new FileReader(""));
,这段代码你是否熟悉,相信学习java开发到字节流、字符流、文件流的内容时都见到了这样的代码,一层嵌套一层,一层嵌套一层,字节流转字符流等等,而这样方式的使用就是装饰器模式的一种体现。
# 外观模式
- 基于SpringBoot开发门面模式中间件,统一控制接口白名单
# 享元模式
- 基于Redis秒杀,提供活动与库存信息查询
# 代理模式
- 模拟mybatis-spring中定义DAO接口,使用代理类方式操作数据库原理实现场景
- 使用过的一些中间件例如;RPC框架,在拿到jar包对接口的描述后,中间件会在服务启动的时候生成对应的代理类,当调用接口的时候,实际是通过代理类发出的socket信息进行通过。
- 另外像我们常用的MyBatis,基本是定义接口但是不需要写实现类,就可以对xml或者自定义注解里的sql语句进行增删改查操作。
# 行为型模式
# 责任链模式
- 项目上线流程多级负责人审批
# 迭代器模式
- 模拟公司组织架构树结构关系
- 深度迭代遍历人员信息
- 日常使用的iterator遍历,jdk为我们提供的list集合遍历
# 中介者模式
- 按照Mybatis原理手写ORM框架,给JDBC方式操作数据库增加中介者
# 备忘录模式
- 互联网系统上线过程中,配置文件回滚场景
- 备忘录模式是以可以恢复或者说回滚,配置、版本、悔棋为核心功能的设计模式,而这种设计模式属于行为模式。在功能实现上是以不破坏原对象为基础增加备忘录操作类,记录原对象的行为从而实现备忘录模式。
# 观察者模式
- 监听消息通知用户
- 简单来讲观察者🕵模式,就是当一个行为发生时传递信息给另外一个用户接收做出相应的处理,两者之间没有直接的耦合关联。
# 状态模式
- 状态流程审核发布上线
# 策略模式
- 模拟多种营销类型优惠券,折扣金额计算策略场景
- 策略模式是一种行为模式,也是替代大量ifelse的利器。它所能帮你解决的是场景,一般是具有同类可替代的行为逻辑算法场景。比如;不同类型的交易方式(信用卡、支付宝、微信)、生成唯一ID策略(UUID、DB自增、DB+Redis、雪花算法、Leaf算法)等,都可以使用策略模式进行行为包装,供给外部使用。
# 模版模式
- 爬虫各类电商商品,生成营销推广海报场景
# 访问者模式
- 家长与校长,对学生和老师的不同视角信息的访问
# 重点
- 创建型模式:工厂方法模式、单例模式
- 结构型模式:适配器模式、装饰器模式、代理模式
- 行为型模式:观察者模式、策略模式、模板方法模式