前缀树,又称为Trie树,是一种树形数据结构,可用于高效地存储和检索字符串数据集合中的键,常用于自动补完和拼写检查等应用场景。下面对是对前缀树节点的定义:

1
2
3
4
class WordNetTree {
boolean end;
WordNetTree[] words = new WordNetTree[26];
}

其中end代表当前节点是否为结尾;words代表每个节点中的集合,数组长度为26,代表每次创建一个WordNetTree节点时,都会在该节点内部创建一个长度为26的WordNetTree数组。

最近看面经经常能看到面试官对ThreadLocal方面的提问,于是就去翻了翻ThreadLocal的源码,发现源码并不长,大概看了一通,能看出其中的七七八八,打算借此来梳理一下。PS:HashMap的源码能看明白,看这个源码也不是问题。

一、基本认识

点进源码,看见ThreadLocaljava.lang包下的类;在网上也看了看其他人对它的概括,加上自己对看完源码后对ThreadLocal的理解:

用于线程之间数据的隔离。简单说就是通过ThreadLocal来开辟一块区间存放数据,这个区间作为线程的本地线程存储,只有当前线程才能获取到这个数据,这个数据对其他线程是不可见的。

可以看到ThreadLocal的公有构造方法:

1
2
public ThreadLocal() {
}

就是用来创建ThreadLocal对象,没有在其中做其他的工作。

平常用ThreadLocal最多的两个方法就是setget两个方法;那我们来看一看这两个方法的源码。

一、介绍

概念:一个类的接口转换成客户端希望的另一个接口。适配器模式让那些接口不兼容的类可以一起工作。即根据已有的接口,生成想要的接口。

先看下面这个小例子体会一下适配器模式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class AppTest {
/**
*
* 符合开闭原则,源代码没有进行修改
* 也符合组合优于继承原则(只是进行复用)
*/
public static void main(String[] args) {
Calculate calculate = new Calculate(); // 原来的接口是接两个
CalcAdapter calcAdapter = new CalcAdapter(calculate); // 做个适配器,可以接收三个
int add = calcAdapter.add(1, 2, 3);
System.out.println(add);
}
}

// 基本计算器
class Calculate {
public int add(int a, int b) {
return a + b;
}
}

// 变化来了,客户想要计算三个数的和 - 采用适配器模式的方式,将接口转换成我们需要的形式
class CalcAdapter {
private Calculate calculate; // 复用其功能,采用组合的方式。组合需要被是适配的类

public CalcAdapter(Calculate calculate) {
this.calculate = calculate;
}

public int add(int a, int b, int c) {
return calculate.add(a, calculate.add(b, c)); // 做到对功能的复用
}
}

一、开闭原则

1.1 概念

开闭原则是设计模式中最重要也是最基本的原则,可以说其它的原则都是为了开闭原则进行服务的。

核心概念:

  1. 一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方)。对抽象构建框架,用实现扩展细节。
  2. 当软件需要实现时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
  3. 编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则。

综合:对扩展新功能是开放的,对修改原有功能是关闭的。也就说,在对功能进行扩展时,是对原有的类上进行扩展(继承、接口设计等等)

本文用来记录工厂模式中,简单工厂、工厂方法和抽象工厂。

一、前置知识

image-20210710144613164

上图中,每个功能可以看成一个模块,每个模块要想能正常、更好的使用,一定也会依赖其他的模块,所以需要满足:

  • 每个模块负责自己的职责(单一职责),各个模块之间通过接口隔离原则对外暴露功能的使用(接口隔离原则)。
  • 每个模块都应该”承诺”自己对外暴露的接口是不变的。当模块内部发生变化时,其他模块是不需要知道的。这便是依赖于抽象而不依赖于实现(依赖倒置原则)
  • 上层模块只需要知道下层模块暴露出的接口即可,至于实现细节不需要也不应该知道。(迪米特法则)

为了对下面的实例代码进行演示,先明确两个概念:

  1. 产品:对应着类。
  2. 抽象产品:抽象类或接口

需求:

设计一个食物的项目,便于食物种类的扩展,且便于维护。

  1. 食物存在各种各样的种类
  2. 客户端可以对其进行扩展自己所需要的食物。

本文用来介绍设计模式中的单例模式。

一、基本介绍

所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例, 并且该类只提供一个取得其对象实例的方法(静态方法)。

并且常见的单例设计模式共有八种:

  • 饿汉式(静态常量)
  • 饿汉式(静态代码块的方式)
  • 懒汉式(线程不安全)
  • 懒汉式(线程安全,同步方法)
  • 懒汉式(线程安全,同步代码块)
  • 双重检查
  • 静态内部类
  • 枚举

接下来,我们将逐一介绍这八种单例设计模式。

单例模式设计步骤如下:

  1. 构造器私有化(防止new)
  2. 类的内部创建对象
  3. 向外暴露一个静态的公共方法。

本章用来叙述设计模式中的接口隔离原则。叙述方式同样采用实例演示的方式。

一、基本介绍

接口隔离原则的核心:客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上。

二、实例介绍

我们现在设计一个接口,接口中有5个功能,分别让B,D类实现这个接口;然后,我们再设计A,C类,其中A,C类分别依赖B,D类;A使用B类中的option1,option2,option3方法;C使用D类中option1,option4,option5方法。