设计模式
课程大纲
类型 | 模式 | 大纲 |
创建型模式 | 单例模式 | 为什么要使用单例 |
案例1:Logger,资源冲突 | ||
案例2:递增Id生成器,全局唯一 | ||
如何实现 | ||
饿汉式 / 懒汉式 / 双重检测 / 静态内部类 / 枚举 | ||
单例存在哪些问题 | ||
替代的解决方案 | ||
单例作用范围 | ||
案例3:线程单例实现 | ||
案例4:进程单例实现 | ||
案例5:集群单例实现 | ||
案例6:Replica多副本实现 | ||
实战主题:IdGenerator | ||
工厂模式 | 简单工厂 | |
案例1:配置文件解析器,if…else | ||
工厂方法 | ||
案例2:mybatis session 创建,工厂方法+简单工厂 | ||
抽象工厂 | ||
案例3:JDBC各配套类,MySQL,Oracle,SQLServer | ||
实战主题:JDK 中 Calendar,DateFormat 里的工厂 | ||
DI容器 | 配置解析 | |
对象创建 | ||
对象生命周期管理 | ||
实战主题:实现自己的简易DI容器 | ||
建造者模式 | 为什么需要建造者模式 | |
案例1:可配置资源池 | ||
实现方式 | ||
与工厂模式的区别 | ||
实战主题:HTTP 管道处理中间件 | ||
结构型模式 | 代理模式 | 代理模式的原理解析 |
案例1:性能计数器 | ||
将框架代码和业务代码解耦 | ||
案例2:代理类 UserControllerProxy 和原始类 UserController | ||
动态代理的原理解析 | ||
基于接口的动态代理 | ||
基于继承的动态代理 | ||
案例3:SpringAOP 底层动态代理机制 | ||
实战主题:使用代理模式实现简单RPC框架 | ||
装饰器模式 | 案例1:Java IO 类的“奇怪”用法 | |
基于继承的设计方案 | ||
“组合优于继承”设计原则 | ||
基于装饰器模式的设计方案 | ||
关键点1:装饰器类和原始类继承同样的父类 | ||
关键点2:装饰器类是对功能的增强 | ||
案例2:FilterInputStream 的实现 | ||
实战主题:商品促销引擎设计 | ||
适配器模式 | 类适配器vs对象适配器 | |
应用场景总结 | ||
案例1:封装有缺陷的接口设计 | ||
案例2:统一多个类的接口设计 | ||
案例3:替换依赖的外部系统 | ||
案例4:JDK 2.0 Iterator 类重构 | ||
实战主题:统一日志框架实现 | ||
门面模式 | 门面模式的原理与实现 | |
迪米特法则(最少知识原则)和接口隔离原则 | ||
解决易用性问题 | ||
解决性能问题 | ||
解决分布式事务问题 | ||
案例1:微服务网关与门面模式 | ||
组合模式 | 组合模式的原理与实现 | |
算法:树的遍历 | ||
案例1:文件系统遍历器 | ||
案例2:电商产品搜索条件接口 | ||
实战主题:组织框架图后台设计 | ||
行为型模式 | 观察者模式 | 原理及应用场景剖析 |
案例1:经典的观察者实现 | ||
基于不同应用场景的不同实现方式 | ||
同步阻塞的实现方式 | ||
异步非阻塞的实现方式 | ||
案例2:异步非阻塞观察者模式的简易实现 | ||
基于 Thread vs 基于 Executor | ||
进程内的实现方式 | ||
跨进程的实现方式 | ||
实战主题:EventBus 框架 | ||
关键数据结构 Observer 注册表的实现 | ||
Java 的反射语法来动态地创建对象、执行函数 | ||
模板方法 | 模板方法模式的原理与实现 | |
案例1:XML生成器 | ||
案例2:Java InputStream - read() 函数 | ||
案例3:Java AbstractList - addAll() 函数 | ||
案例4:HttpServlet 的 service() 函数 | ||
案例5:TestCase 类的setUp()、tearDown() 函数 | ||
实战主题:可配置分析引擎 | ||
策略模式 | 策略模式的原理与实现 | |
如何利用策略模式避免分支判断? | ||
案例1:银行贷款计算模块的策略化重构 | ||
实战主题:根据文件大小进行排序策略选择程序 | ||
职责链模式 | 职责链模式的原理和实现 | |
案例1:简单职责链实现 | ||
案例2:职责链 + 模板方法 防止链式节点缺失Bug | ||
案例3:Servlet Filter | ||
案例4:Tomcat 的 ApplicationFilterChain 类 | ||
案例5:Spring Interceptor | ||
实战主题:敏感词过滤器 | ||
状态模式 | 什么是有限状态机? | |
案例1:状态机实现方式一:分支逻辑法 | ||
案例2:状态机实现方式二:查表法 | ||
案例3:状态机实现方式三:状态模式 | ||
实战主题:电梯按钮 | ||
迭代器模式 | 迭代器模式的原理和实现 | |
迭代器模式的优势 | ||
在遍历的同时增删集合元素会发生什么? | ||
如何应对遍历时改变集合导致的未决行为? | ||
如何在遍历的同时安全地删除集合元素? | ||
实战主题:实现一个支持“快照”功能的迭代器 | ||
命令模式 | 命令模式的原理解读 | |
案例1:QQ 卡丁车 | ||
命令模式 VS 策略模式 | ||
实战主题:Restful API 处理函数 |
分布式架构
课程大纲
模块 | 内容 |
分布式架构基础 | 远程服务调用: 技术与演化 |
REST 设计风格 | |
本地事务 - 原子性/持久性/隔离性 | |
全局事务 - 2PC | |
分布式事务:CAP 与 ACID | |
可靠事件队列与SAGA事务 | |
客户端缓存 | |
服务端缓存 | |
客户端负载均衡:缓存与代理负载均衡器 | |
服务端负载均衡:网络层LB与应用层LB各自实现什么功能 | |
服务发现与网关路由 | |
服务容错与流量控制 | |
事件日志/ 链路追踪 / 聚合度量 | |
分布式架构中的缓存 | 演进1:从单体架构看缓存 |
演进2:从集群架构看缓存 | |
演进3:从微服务架构看缓存 | |
分类1:客户端缓存的分类和介绍 | |
分类2:服务端缓存的分类和介绍 | |
缓存规范:JSR107 | |
深⼊介绍GuavaCache的原理 | |
深⼊介绍SpringCache的原理与实现 | |
Redis与Reactor模式 | |
Redis的分片、集群用法 | |
Redis多线程模型解读 | |
缓存穿透:发⽣场景和常⻅的破解招数 | |
缓存雪崩:发生场景和常见的破解招数 | |
缓存一致性:多级缓存与数据库之间的⼀致性怎么保证 | |
分布式并发锁1:利用Redis来自己实现 | |
分布式并发锁2:利用RedLock实现分布式并发锁以及常见的坑 | |
分布式并发锁3:利用缓存做分布式锁 | |
Session共享:如何利用缓存来实现 | |
多机房:缓存在多机房场景下如何应用 | |
微服务统一配置中心:如何利用缓存来保存配置数据 | |
案例:秒杀是如何利用缓存来实现库存扣减 | |
案例:在高并发场景下如何使用缓存来保存配置数据 | |
分布式架构中的消息队列 | 如何选择消息队列? |
消息模型:主题和队列 | |
利用事务消息实现分布式事务 | |
如何确保消息不会丢失 | |
如何处理消费过程中的重复消息 | |
使用异步设计提升系统性能 | |
如何实现高性能的异步网络传输? | |
序列化与反序列化 | |
缓存策略:使用缓存来减少磁盘IO | |
使用锁保护共享数据,协调异步线程 | |
用硬件同步原语(CAS)替代锁 | |
KafkaConsumer源码分析:消息消费的实现过程 | |
Kafka的协调服务ZooKeeper:实现分布式系统的“瑞士军刀” | |
Kafka中如何实现事务 | |
案例:动手实现一个简单的RPC框架1:原理和程序的结构 | |
案例:动手实现一个简单的RPC框架2:通信与序列化 | |
案例:动手实现一个简单的RPC框架3:客户端 | |
案例:动手实现一个简单的RPC框架4:服务端 |