将具有静态属性的单例更改为多例
Change a Singleton with static properties into a Multiton
我有以下单例class
public class TestFileEngine {
private static int counter = 0;
private static List<GeneratedFile> generatedFileList;
private static Optional<TestFileEngine> engine = Optional.empty();
private TestFileEngine() {
generatedFileList = Collections.synchronizedList(new ArrayList<>());
}
public static synchronized TestFileEngine getInstance() {
if (!engine.isPresent()) {
engine = Optional.of(new TestFileEngine());
}
return ruEngine.get();
}
public synchronized void generateFile() {
counter++;
String timestamp = LocalDateTime.now().toString();
String content = "";//insert random content generation
GeneratedFile gf = new GeneratedFile(counter + ".txt", timestamp, content);
generatedFileList.add(gf);
System.out.println("Generated file " + counter + ".txt");
}
public GeneratedFile findFileByName(String filename) {
for (GeneratedFile file : generatedFileList){
if(file.getFileName().equals(filename)){
return file;
}
}
return null;
}
}
现在我想要两个独立的引擎(将来可能更多),用于跟踪目的,我偶然发现了 multiton 模式,仍然使用惰性实现。所以我将更改以下内容:
//Getting rid of Optional, as it can get funky with Maps
private static final Map<String, TestFileEngine> _engines = new HashMap<String, TestFileEngine>();
public static synchronized TestFileEngine getInstance(String key) {
if (_engines.get(key) == null) {
_engines.put(key, new TestFileEngine());
System.out.println("Create engine " + key);
}else {
System.out.println("Using engine " + key);
}
return _engines.get(key);
}
我想确保每个引擎都有其独立的计数器和文件列表。但是在我 运行 以下代码之后,它们似乎共享计数器和列表:
TestFileEngine.getInstance("http").generateFile();
TestFileEngine.getInstance("http").generateFile();
TestFileEngine.getInstance("http").generateFile();
TestFileEngine.getInstance("ftp").generateFile();
TestFileEngine.getInstance("ftp").generateFile();
System.out.println(TestFileEngine.getInstance("http").findFileByName("4.txt").getFileName());
System.out.println(TestFileEngine.getInstance("ftp").findFileByName("2.txt"));
控制台:
Create engine http
Generated file 1.txt
Using engine http
Generated file 2.txt
Using engine http
Generated file 3.txt
Create engine ftp
Generated file 4.txt
Using engine ftp
Generated file 5.txt
Using engine http
4.txt
Using engine ftp
null
我应该如何处理 counter
和 generatedFileList
字段,以便从 Multiton 创建的每个 TestFileEngine
完全分开?
实际上,您使用 static
修饰符声明了 class 的 3 个字段:
private static int counter = 0;
private static List<GeneratedFile> generatedFileList;
private static final Map<String, TestFileEngine> _engines = new HashMap<String, TestFileEngine>();
static
字段在当前 class.
的所有实例之间共享
您想要 engines
字段。
但是您不希望 counter
和 generatedFileList
字段必须附加到 TestFileEngine
的特定实例。
所以让它们成为实例字段而不是 static
.
作为旁注,int
字段默认值为 0
,您应该避免 _
为不属于命名约定的变量添加前缀。
所以你可以写:
private int counter;
private List<GeneratedFile> generatedFileList;
private static final Map<String, TestFileEngine> engines = new HashMap<String, TestFileEngine>();
我有以下单例class
public class TestFileEngine {
private static int counter = 0;
private static List<GeneratedFile> generatedFileList;
private static Optional<TestFileEngine> engine = Optional.empty();
private TestFileEngine() {
generatedFileList = Collections.synchronizedList(new ArrayList<>());
}
public static synchronized TestFileEngine getInstance() {
if (!engine.isPresent()) {
engine = Optional.of(new TestFileEngine());
}
return ruEngine.get();
}
public synchronized void generateFile() {
counter++;
String timestamp = LocalDateTime.now().toString();
String content = "";//insert random content generation
GeneratedFile gf = new GeneratedFile(counter + ".txt", timestamp, content);
generatedFileList.add(gf);
System.out.println("Generated file " + counter + ".txt");
}
public GeneratedFile findFileByName(String filename) {
for (GeneratedFile file : generatedFileList){
if(file.getFileName().equals(filename)){
return file;
}
}
return null;
}
}
现在我想要两个独立的引擎(将来可能更多),用于跟踪目的,我偶然发现了 multiton 模式,仍然使用惰性实现。所以我将更改以下内容:
//Getting rid of Optional, as it can get funky with Maps
private static final Map<String, TestFileEngine> _engines = new HashMap<String, TestFileEngine>();
public static synchronized TestFileEngine getInstance(String key) {
if (_engines.get(key) == null) {
_engines.put(key, new TestFileEngine());
System.out.println("Create engine " + key);
}else {
System.out.println("Using engine " + key);
}
return _engines.get(key);
}
我想确保每个引擎都有其独立的计数器和文件列表。但是在我 运行 以下代码之后,它们似乎共享计数器和列表:
TestFileEngine.getInstance("http").generateFile();
TestFileEngine.getInstance("http").generateFile();
TestFileEngine.getInstance("http").generateFile();
TestFileEngine.getInstance("ftp").generateFile();
TestFileEngine.getInstance("ftp").generateFile();
System.out.println(TestFileEngine.getInstance("http").findFileByName("4.txt").getFileName());
System.out.println(TestFileEngine.getInstance("ftp").findFileByName("2.txt"));
控制台:
Create engine http
Generated file 1.txt
Using engine http
Generated file 2.txt
Using engine http
Generated file 3.txt
Create engine ftp
Generated file 4.txt
Using engine ftp
Generated file 5.txt
Using engine http
4.txt
Using engine ftp
null
我应该如何处理 counter
和 generatedFileList
字段,以便从 Multiton 创建的每个 TestFileEngine
完全分开?
实际上,您使用 static
修饰符声明了 class 的 3 个字段:
private static int counter = 0;
private static List<GeneratedFile> generatedFileList;
private static final Map<String, TestFileEngine> _engines = new HashMap<String, TestFileEngine>();
static
字段在当前 class.
的所有实例之间共享
您想要 engines
字段。
但是您不希望 counter
和 generatedFileList
字段必须附加到 TestFileEngine
的特定实例。
所以让它们成为实例字段而不是 static
.
作为旁注,int
字段默认值为 0
,您应该避免 _
为不属于命名约定的变量添加前缀。
所以你可以写:
private int counter;
private List<GeneratedFile> generatedFileList;
private static final Map<String, TestFileEngine> engines = new HashMap<String, TestFileEngine>();