我有几个类可以作为一些重型库的包装器,例如解析器,标记器和其他资源。所有这些库都有一个共同点:它们有一个load / init方法,它将序列化模型(一个大文件)作为输入,并返回一个可用于执行具体事务的类,如解析文本。
为了说明这种情况,假设我有一个ConcreteParser lib来进行解析,为此我创建了以下类来包装它:
public class ParserWrapper {
private static final ConcreteParser parser = null;
private static void init(String modelFileName) {
if (parser == null)
parser = ConcreteParser.load(modelFileName);
}
public static Result parse(input) {
if (parser == null) throw new RuntimeException(...);
return parser.parse(input);
}
}
正如您所看到的,这需要客户端在解析之前首先调用init,这绝对是禁止的。我也尝试过基于Singleton模式的解决方案,但我仍然认为有更好的方法来做我想要的。
ConcreteParser是静态的,因为每个模型都需要相对较长的时间来加载,并占用大量内存。因此,我需要在使用它的每个类之间共享它们。
所以,我的问题是:是否有其他(更优雅)的方式来做我想要的?我该如何改进这段代码?我想创建一个类ResourceManager,它有几个方法,如“createParser”和“createTagger”,以便有一个点来加载资源。该类还将检查每个资源是否已经实例化,等等。这些都有吗?
问候。
答案 0 :(得分:3)
我会创建类似Factory的类来创建Parser和Tager等,并为某些文件名设置此类缓存结果,以便第一次调用getParser(filename)将导致创建解析器,并且所有下一个将返回缓存解析器。 这与Singleton类似,但是如果你有一个通用的factorys接口允许创建一个返回模拟的工厂,而不是创建整个解析器。
这样,您只需要确保程序中的某个位置为所有解析器和标记器创建工厂,并且可以从程序中获取此对象。
答案 1 :(得分:1)
似乎解析器是不可变的。 (如果解析器不为null,init什么都不做)那么为什么还要把它变成静态呢?使init成为构造函数并解析ParswerWrapper的成员。创建另一个类(或使用System.setProperty()作为一个丑陋的黑客),这是一个Singleton,其唯一的工作是保留引用。如果您提前知道需要哪些文件,甚至可以使用Enum!
#1
/*package*/ class ParserWrapper implements ParserWrapperInterface{
private ConcreteParser p;
public ParserWrapper(String filename) {
p = ConcreteParser.load(p);
}
public Result parse(InputStream in) {...}
}
public Enum ParserManager {
instance;
private Map<String, ParserWrapper> map = new HashMap<...>()
public get(String filename) {
if(!map.containesKey(filename)) {
synchronized(ParserManager.class) {
if(!map.containesKey(filename)) {
map.put(filename, new ParserWrapper(filename));
}
}
}
return map.get(filename);
}
}
#2
public Enum Parsers {
ModelFoo("foo.mdl"), ModelBar("bar.mdl");
private ConcreteParser p;
public Parser(String fname) {
p = ConcreteParser.load(fname);
}
public Result parse(InputStream in) {...}
}
使用Enum保证每个Enum值只有一个实例。期。 JVM被假定为不能克隆,反序列化,在类加载器之间拆分等。枚举意味着单个实例。
答案 2 :(得分:0)
为什么不将ResourceManager设置为静态,然后在初始化包装器之前调用所有的create方法?这避免了单例模式,可能更符合你想要达到的目标。
答案 3 :(得分:0)
文件是否会改变?
如果不是:将其作为静态intialiser中的资源加载。
如果是这样的话:“从上面参数化”通过构造函数传递对象,一直向下。