单例变量命名的意义

先来看一个简单的使用 Java 语言的单例模式,如下:

1
2
3
4
5
6
7
public class FileSystem {

public static final FileSystem singleton = new FileSystem();

private FileSystem() {}

}

实现单例模式有多种方式,这里想要讨论的点是关 singleton 这个单例使用不同名字所表现出的意义

在iOS平台,swift 官方库中,常常会见到以下单例命名:

1
2
3
4
FileManager.default
Bundle.main
SessionManager.default
URLSession.shared

而在 Java 中通常会使用一个方法:(懒加载模式)

1
Singleton.getInstance()

在写了和使用了无数单例之后,我自己对于单例变量的命名也开始有了要求了,这里给出我自己的思考

假定我们要实现一个文件系统IO

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
// FileSystem.java
interface FileSystem {

public static final FileSystem singleton = new FileSystemImpl("/");

String readFile(String path);

}

// FileSystemImpl.java
public class FileSystemImpl implements FileSystem {

public final String rootPath;

protected constructor(String rootPath) {
this.rootPath = rootPath;
}

public String readFile(String path) {
// ...
}

}

// 使用
FileSystem.singleton.readFile("/some/absolute/path");
FileSystem.singleton.readFile("some/relative/path");

一切都显得非常合理,接下来做一些优化,当我们需要经常读取某几个路径下的文件,或者说有时我们想限制在某个路径下读取文件,刚可以如下做

1
2
3
4
5
6
7
interface FileSystem {

public static final FileSystem default = new FileSystemImpl("/");
public static final FileSystem user = new FileSystemImpl("/Users/mingo");
public static final FileSystem document = new FileSystemImpl("/Users/mingo/Docuemnts");

}

当一个单例会出现有限的多例时,命明的意义就出现了,singleton 给人的感觉是这个类只能是个单例,不能再创建,而 default 给人的感觉就是这个类默认使用 default ,可以再创建用于其他用途的。

这就是单例变量命名的意义,虽然作用不大,可以一直使用singleton就行,但如果我们追求明确的语义时,singleton 就显得无意义了。

下面给出一种和 singleton 同样无意义的命名:

1
2
3
4
5
public class UserManager {

public static final UserManager manager = new UserManager()

}

manager 同样也表现出无意义,甚至不如 singleton ,至少 singleton 还表现出了这是一个单例变量,而 manager 却要求我们检查一下代码才知道。因此在团队合作中最好使用一个固定的变量名,比如:

  • singleton 表示唯一单例
  • default 表示创建出来的单例使用的是默认参数
  • 其他有意义的命名 表示有意义的用途