Skip to content

Commit 09d095a

Browse files
committed
整理设计模式
1 parent 1aa96b2 commit 09d095a

File tree

87 files changed

+986
-528
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+986
-528
lines changed

README.md

+24-8
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,29 @@
207207
1. [线上接口很慢怎么办?](docs/practice/service-performance-optimization.md)
208208
2. [干掉 “重复代码” 的技巧有哪些](docs/advance/excellent-article/4-remove-duplicate-code.md)
209209

210+
- docs/campus-recruit/interview/9-huawei.md)
211+
- [网易](docs/campus-recruit/interview/10-netease.md)
212+
213+
# 设计模式
214+
215+
[字节跳动大佬总结的设计模式PDF](https://t.1yb.co/y96J)
216+
217+
[设计模式的六大原则](https://topjavaer.cn/advance/design-pattern/1-principle.html)
218+
219+
常见的**设计模式**详解:
220+
221+
- [设计模式之单例模式](https://topjavaer.cn/advance/design-pattern/2-singleton.html)
222+
- [设计模式之工厂模式](https://topjavaer.cn/advance/design-pattern/3-factory.html)
223+
- [设计模式之模板模式](https://topjavaer.cn/advance/design-pattern/4-template.html)
224+
- [设计模式之策略模式](https://topjavaer.cn/advance/design-pattern/5-strategy.html)
225+
- [设计模式之责任链模式](https://topjavaer.cn/advance/design-pattern/6-chain.html)
226+
- [设计模式之迭代器模式](https://topjavaer.cn/advance/design-pattern/7-iterator.html)
227+
- [设计模式之装饰器模式](https://topjavaer.cn/advance/design-pattern/8-decorator.html)
228+
- [设计模式之适配器模式](https://topjavaer.cn/advance/design-pattern/9-adapter.html)
229+
- [设计模式之观察者模式](https://topjavaer.cn/advance/design-pattern/10-observer.html)
230+
- [设计模式之代理模式](https://topjavaer.cn/advance/design-pattern/11-proxy.html)
231+
- [设计模式之建造者模式](https://topjavaer.cn/advance/design-pattern/12-builder.html)
232+
210233
# 大厂面经汇总
211234

212235
- [字节跳动](docs/campus-recruit/interview/1-byte-and-dance.md)
@@ -217,14 +240,7 @@
217240
- [美团](docs/campus-recruit/interview/6-meituan.md)
218241
- [shopee](docs/campus-recruit/interview/7-shopee.md)
219242
- [京东](docs/campus-recruit/interview/8-jingdong.md)
220-
- [华为](docs/campus-recruit/interview/9-huawei.md)
221-
- [网易](docs/campus-recruit/interview/10-netease.md)
222-
223-
# 设计模式
224-
225-
[字节跳动大佬总结的设计模式PDF](https://t.1yb.co/y96J)
226-
227-
[设计模式总结](https://topjavaer.cn/advance/design-pattern/)
243+
- [华为](
228244

229245
# 优质文章
230246

docs/README.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ projects:
4141

4242
**希望我的分享可以帮助更多的小伙伴,我踩过的坑你们不要再踩**
4343

44-
[<img src="https://img.shields.io/badge/Wechat-微信交流群-success">](http://img.dabin-coder.cn/image/微信群.png)
44+
[<img src="https://img.shields.io/badge/Wechat-微信交流群-success">](http://img.topjavaer.cn/img/微信群.png)
4545
[<img src="https://img.shields.io/badge/公众号-程序员大彬-orange">](https://mp.weixin.qq.com/s?__biz=Mzg2OTY1NzY0MQ==&mid=2247488751&idx=1&sn=507e27534b6ea5f4b3771b30e1fcf57e&chksm=ce98e9a9f9ef60bfbf1370899b49181bae5247e5935714f7ad9e3d06c0028a25c0bfc34d4441#rd)
4646
[<img src="https://img.shields.io/badge/哔哩哔哩-我是大彬呀-pink">](https://space.bilibili.com/1729916794)
4747
[<img src="https://img.shields.io/badge/知乎-程序员大彬-blue">](https://www.zhihu.com/people/dai-shu-bin-13)
@@ -57,7 +57,7 @@ projects:
5757

5858
## 学习路线
5959

60-
![](http://img.dabin-coder.cn/image/20220530232715.png)
60+
![](http://img.topjavaer.cn/img/20220530232715.png)
6161

6262
> 微信搜索【程序员大彬】,回复【学习路线】获取**高清图**
6363
@@ -67,15 +67,15 @@ projects:
6767

6868
交流群学习氛围很浓厚,截个图给大家感受下。
6969

70-
<img src="http://img.dabin-coder.cn/image/交流群1.png" />
70+
<img src="http://img.topjavaer.cn/img/交流群1.png" />
7171

72-
![](http://img.dabin-coder.cn/image/交流群2.png)
72+
![](http://img.topjavaer.cn/img/交流群2.png)
7373

74-
<img src="http://img.dabin-coder.cn/image/交流群3.png" style="zoom: 50%;" />
74+
<img src="http://img.topjavaer.cn/img/交流群3.png" style="zoom: 50%;" />
7575

7676
感兴趣的小伙伴可以扫描下方的二维码**加我微信****备注加群**,我拉你进群,一起学习成长!
7777

78-
![](http://img.dabin-coder.cn/image/微信加群.png)
78+
![](http://img.topjavaer.cn/img/微信加群.png)
7979

8080
## 参与贡献
8181

docs/about/contact.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ sidebar: heading
66

77
如果有什么疑问或者建议,欢迎添加大彬微信进行交流~
88

9-
<div align="center"><img src="http://img.dabin-coder.cn/image/个人微信索隆.jpg" style="zoom:50%;" />
9+
<div align="center"><img src="http://img.topjavaer.cn/img/个人微信索隆.jpg" style="zoom:50%;" />
1010
<p></p>
1111
</div>
1212

@@ -16,12 +16,12 @@ sidebar: heading
1616

1717
交流群学习氛围很浓厚,截个图给大家感受下。
1818

19-
<img src="http://img.dabin-coder.cn/image/交流群1.png" />
19+
<img src="http://img.topjavaer.cn/img/交流群1.png" />
2020

21-
![](http://img.dabin-coder.cn/image/交流群2.png)
21+
![](http://img.topjavaer.cn/img/交流群2.png)
2222

23-
<img src="http://img.dabin-coder.cn/image/交流群3.png" style="zoom: 50%;" />
23+
<img src="http://img.topjavaer.cn/img/交流群3.png" style="zoom: 50%;" />
2424

2525
感兴趣的小伙伴可以扫描下方的二维码**加我微信****备注加群**,我拉你进群,一起学习成长!
2626

27-
![](http://img.dabin-coder.cn/image/微信加群.png)
27+
![](http://img.topjavaer.cn/img/微信加群.png)

docs/about/introduce.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ sidebar: heading
77

88
我是非科班出身,本科学的不是计算机,大四开始自学Java,并且找到了中大厂的offer。自学路上遇到不少问题,每天晚上都是坚持到一两点才睡觉,**最终也拿到了30w的offer**
99

10-
![](http://img.dabin-coder.cn/image/image-20211206000941636.png)
10+
![](http://img.topjavaer.cn/img/image-20211206000941636.png)
1111

1212
下面来说说自己的经历吧(附自学路线)。
1313

docs/advance/concurrent/1-current-limiting.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
令牌桶(token bucket)算法,指的是设计一个容器(即“桶”),由某个组件持续运行往该容器中添加令牌(token),令牌可以是简单的数字、字符或组合,也可以仅仅是一个计数,然后每个请求进入系统时,需要从桶中领取一个令牌,所有请求都必须有令牌才能进入后端系统。当令牌桶空时,拒绝请求;当令牌桶满时,不再往其中添加新的令牌。
88
令牌桶算法的架构如图1所示:
99

10-
![](http://img.dabin-coder.cn/image/限流1.png)
10+
![](http://img.topjavaer.cn/img/限流1.png)
1111

1212
令牌桶算法的实现逻辑如下:
1313

@@ -33,7 +33,7 @@
3333

3434
漏桶算法的架构如图所示:
3535

36-
![](http://img.dabin-coder.cn/image/限流2.png)
36+
![](http://img.topjavaer.cn/img/限流2.png)
3737

3838
漏桶算法的实现逻辑如下:
3939

@@ -85,23 +85,23 @@
8585

8686
假设我们的时间段T是1秒,请求最大值是10,在第一秒内,请求数量分布是第500毫秒时有1个请求,第800毫秒时有9个请求,如图3所示:
8787

88-
![](http://img.dabin-coder.cn/image/限流3.png)
88+
![](http://img.topjavaer.cn/img/限流3.png)
8989

9090
这是对于第一秒而言,这个请求分布是合理的。
9191

9292
此时第二秒的第200毫秒(即两秒中的第1200毫秒)内,又来了10个请求,如图4所示:
9393

94-
![](http://img.dabin-coder.cn/image/限流4.png)
94+
![](http://img.topjavaer.cn/img/限流4.png)
9595

9696
单独看第二秒依然是合理的,但是两个时间段连在一起的时候,就出现了问题,如图5所示:
9797

98-
![](http://img.dabin-coder.cn/image/限流5.png)
98+
![](http://img.topjavaer.cn/img/限流5.png)
9999

100100
从500毫秒到1200毫秒,短短700毫秒的时间内后端服务器就接收了20个请求,这显然违背了一开始我们希望1秒最多10个的初衷。这种远远大于预期流量的流量加到后端服务器头上,是会造成不可预料的后果的。因此,人们改进了固定窗口的算法,将其改为检查任何一个时间段都不超过请求数量阈值的时间窗口算法:滑动时间窗口算法。
101101

102102
滑动时间窗口算法要求当请求进入系统时,回溯过去的时间段T,找到其中的请求数量,然后决定是否接受当前请求,因此,滑动时间窗口算法需要记录时间段T内请求到达的时间点,逻辑如图6所示:
103103

104-
![](http://img.dabin-coder.cn/image/限流6.png)
104+
![](http://img.topjavaer.cn/img/限流6.png)
105105

106106
解释如下:
107107

@@ -123,7 +123,7 @@
123123

124124
队列法与漏桶算法很类似,都是将请求放入到一个区域,然后业务服务器从中提取请求,但是队列法采用的是完全独立的外部系统,而不是依附于限流系统。队列法的架构如图7所示:
125125

126-
![](http://img.dabin-coder.cn/image/限流7.png)
126+
![](http://img.topjavaer.cn/img/限流7.png)
127127

128128
与漏桶算法相比,队列法的优势如下:
129129

docs/advance/concurrent/2-load-balance.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212

13-
![](http://img.dabin-coder.cn/image/负载均衡1.jpg)
13+
![](http://img.topjavaer.cn/img/负载均衡1.jpg)
1414

1515

1616

@@ -34,7 +34,7 @@
3434

3535

3636

37-
![](http://img.dabin-coder.cn/image/负载均衡2.jpg)
37+
![](http://img.topjavaer.cn/img/负载均衡2.jpg)
3838

3939

4040

@@ -46,7 +46,7 @@
4646

4747

4848

49-
![](http://img.dabin-coder.cn/image/负载均衡3.jpg)
49+
![](http://img.topjavaer.cn/img/负载均衡3.jpg)
5050

5151

5252

@@ -58,7 +58,7 @@
5858

5959

6060

61-
![](http://img.dabin-coder.cn/image/负载均衡4.jpg)
61+
![](http://img.topjavaer.cn/img/负载均衡4.jpg)
6262

6363

6464

@@ -70,7 +70,7 @@
7070

7171

7272

73-
![](http://img.dabin-coder.cn/image/负载均衡5.jpg)
73+
![](http://img.topjavaer.cn/img/负载均衡5.jpg)
7474

7575

7676

docs/advance/design-pattern-all.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ instance = memory;   // 3:设置instance指向刚分配的内存地址
8484

8585
它与饿汉模式一样,也是利用了类初始化机制,因此不存在多线程并发的问题。不一样的是,它是在内部类里面去创建对象实例。这样的话,只要应用中不使用内部类,JVM就不会去加载这个单例类,也就不会创建单例对象,从而实现懒汉式的延迟加载。也就是说这种方式可以同时保证延迟加载和线程安全。
8686

87-
![](http://img.dabin-coder.cn/image/singleton-class-init.png)
87+
![](http://img.topjavaer.cn/img/singleton-class-init.png)
8888

8989
基于类初始化的方案的实现代码更简洁。
9090

@@ -188,7 +188,7 @@ reader.read();
188188

189189
多了一层抽象,减少了工厂的数量(HpMouseFactory和HpKeyboFactory合并为HpFactory)。
190190

191-
![](http://img.dabin-coder.cn/image/抽象工厂.png)
191+
![](http://img.topjavaer.cn/img/抽象工厂.png)
192192

193193

194194

@@ -203,7 +203,7 @@ reader.read();
203203

204204
示例图如下:
205205

206-
![](http://img.dabin-coder.cn/image/模板方法.jpg)
206+
![](http://img.topjavaer.cn/img/模板方法.jpg)
207207

208208
以游戏为例。创建一个抽象类,它的模板方法被设置为 final,这样它就不会被重写。
209209

@@ -288,7 +288,7 @@ public class TemplatePatternDemo {
288288

289289
示例图如下:
290290

291-
![](http://img.dabin-coder.cn/image/策略模式.png)
291+
![](http://img.topjavaer.cn/img/策略模式.png)
292292

293293
以计算器为例,如果我们想得到两个数字相加的和,我们需要用到“+”符号,得到相减的差,需要用到“-”符号等等。虽然我们可以通过字符串比较使用if/else写成通用方法,但是计算的符号每次增加,我们就不得不加在原先的方法中进行增加相应的代码,如果后续计算方法增加、修改或删除,那么会使后续的维护变得困难。
294294

@@ -632,11 +632,11 @@ InputStream in = new LowerCaseInputStream(
632632

633633
对象适配器模式通过组合对象进行适配。
634634

635-
![](http://img.dabin-coder.cn/image/适配器对象适配,png)
635+
![](http://img.topjavaer.cn/img/适配器对象适配,png)
636636

637637
类适配器通过继承来完成适配。
638638

639-
![](http://img.dabin-coder.cn/image/适配器-类继承,png)
639+
![](http://img.topjavaer.cn/img/适配器-类继承,png)
640640

641641
适配器模式的**优点**
642642

docs/advance/design-pattern/2-singleton.md

+61-6
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,40 @@ public class Singleton {
4040

4141
饿汉式单例的**缺点**:单例对象的创建,不是**延时加载**
4242

43-
## 双重检查锁定
43+
## 懒汉式
4444

45-
双重校验锁先判断 instance 是否已经被实例化,如果没有被实例化,那么才对实例化语句进行加锁
45+
与饿汉式思想不同,懒汉式支持延时加载,将对象的创建延迟到了获取对象的时候。不过为了线程安全,在获取对象的操作需要加锁,这就导致了低性能
4646

47-
instance使用static修饰的原因:getInstance为静态方法,因为静态方法的内部不能直接使用非静态变量,只有静态成员才能在没有创建对象时进行初始化,所以返回的这个实例必须是静态的。
47+
```java
48+
public class Singleton {
49+
private static final Singleton instance;
50+
51+
private Singleton () {}
52+
53+
public static synchronized Singleton getInstance() {
54+
if (instance == null) {
55+
instance = new Singleton();
56+
}
57+
58+
return instance;
59+
}
60+
}
61+
```
62+
63+
上述代码加的锁只有在第一次创建对象时有用,而之后每次获取对象,其实是不需要加锁的(双重检查锁定优化了这个问题)。
64+
65+
懒汉式单例**优点**
66+
67+
- 对象的创建是线程安全的。
68+
- 支持延时加载。
69+
70+
懒汉式单例**缺点**
71+
72+
- 获取对象的操作被加上了锁,影响了并发性能。
73+
74+
## 双重检查锁定
75+
76+
双重检查锁定将懒汉式中的 `synchronized` 方法改成了 `synchronized` 代码块。如下:
4877

4978
```
5079
public class Singleton {
@@ -62,6 +91,10 @@ public class Singleton {
6291
}
6392
}
6493
```
94+
双重校验锁先判断 instance 是否已经被实例化,如果没有被实例化,那么才对实例化语句进行加锁。
95+
96+
instance使用static修饰的原因:getInstance为静态方法,因为静态方法的内部不能直接使用非静态变量,只有静态成员才能在没有创建对象时进行初始化,所以返回的这个实例必须是静态的。
97+
6598
为什么两次判断`instance == null`
6699

67100
| Time | Thread A | Thread B |
@@ -94,12 +127,16 @@ instance = memory;   // 3:设置instance指向刚分配的内存地址
94127
| T7 | | 访问`instance`(此时对象还未完成初始化) |
95128
| T8 | 初始化`instance` | |
96129

130+
双重检查锁定单例**优点**
131+
132+
- 对象的创建是线程安全的。
133+
- 支持延时加载。
134+
- 获取对象时不需要加锁。
135+
97136
## 静态内部类
98137

99138
它与饿汉模式一样,也是利用了类初始化机制,因此不存在多线程并发的问题。不一样的是,它是在内部类里面去创建对象实例。这样的话,只要应用中不使用内部类,JVM就不会去加载这个单例类,也就不会创建单例对象,从而实现懒汉式的延迟加载。也就是说这种方式可以同时保证延迟加载和线程安全。
100139

101-
![](http://img.dabin-coder.cn/image/singleton-class-init.png)
102-
103140
基于类初始化的方案的实现代码更简洁。
104141

105142
```
@@ -113,5 +150,23 @@ public class Instance {
113150
}
114151
}
115152
```
116-
但基于volatile的双重检查锁定的方案有一个额外的优势:除了可以对静态字段实现延迟初始化外,还可以对实例字段实现延迟初始化。字段延迟初始化降低了初始化类或创建实例的开销,但增加了访问被延迟初始化的字段的开销。在大多数时候,正常的初始化要优于延迟初始化。
153+
如上述代码,`InstanceHolder` 是一个静态内部类,当外部类 `Instance` 被加载的时候,并不会创建 `InstanceHolder` 实例对象。
154+
155+
只有当调用 `getInstance()` 方法时,`InstanceHolder` 才会被加载,这个时候才会创建 `Instance``Instance` 的唯一性、创建过程的线程安全性,都由 JVM 来保证。
156+
157+
静态内部类单例**优点**
158+
159+
- 对象的创建是线程安全的。
160+
- 支持延时加载。
161+
- 获取对象时不需要加锁。
162+
163+
## 枚举
164+
165+
用枚举来实现单例,是最简单的方式。这种实现方式通过 **Java 枚举**类型本身的特性,保证了实例创建的线程安全性和实例的唯一性。
166+
167+
```java
168+
public enum Singleton {
169+
INSTANCE; // 该对象全局唯一
170+
}
171+
```
117172

0 commit comments

Comments
 (0)