- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在设计一个可以支持不同数据源的模块。我的模块获取用户的公司 ID 作为输入,我必须根据公司 ID 调用适当的类。我正在尝试合并一些好的设计并尽可能避免条件语句。
我有一个使用此方法的 FetchDataSource 单例类。
public class FetchDataSourceSingleton {
private static Map<String, Communicator> communicatorMap;
public static Communicator getCommunicatorInstance(String dataSourceType) {
if (communicatorMap == null || communicatorMap.isEmpty())
populateCommunicatorMap();
if (communicatorMap.containsKey(dataSourceType))
return communicatorMap.get(dataSourceType);
return null;
}
.... other methods including populateCommunicatorMap()
}
“Communicator”是一个接口(interface),communicator map 会返回合适的实例。这是同一个单例类中的 populateCommunicatorMap() 方法。
private static void populateCommunicatorMap() {
communicatorMap = new HashMap<String, Communicator>();
communicatorMap.put("AD", new ADCommunicator());
communicatorMap.put("DB2", new DB2Communicator());
communicatorMap.put("MYSQL", new MYSQLCommunicator());
}
ADCommunicator、DB2Communicator 和 MYSQLCommunicator 将实现 Communicator 接口(interface)。
代码似乎在我的测试稿中有效。我唯一担心的是 HashMap 将为所有相同类型的通信请求返回相同的对象。如果我想避免条件语句,我似乎无法避免在 hashmap 中使用相同的实例。否则我可以像这样调用而不是散列图。
Communicator comm;
if (type = "AD") comm = new ADCommunicator();
if (type = "DB2") comm = new DB2Communicator();
if (type = "MYSQL") comm = new MYSQLCommunicator();
我通过使用散列图根据类型返回实例来避免这种情况。但是我无法避免获得相同实例的单例问题。
在需要同时支持数十万个通信请求的多线程环境中,考虑到我需要在每个 Communicator 类中同步大量代码,这可能是个问题。有没有一种方法可以避免同步并使其线程安全而不影响性能?
最佳答案
I can't seem to avoid having the same instance in the hashmap
您可以使用一个开关而不是一堆 ifs。
将 type
更改为 Java 5+ 中的枚举,然后您可以打开它。为了类型安全,我一般建议使用枚举。
// type is-a enum Communicator.TYPE
switch(type) {
case AD: return new ADCommunicator();
case DB2: return new DB2Communicator();
case MYSQL: return new MYSQLCommunicator();
default: return null;
}
Java 8 可以直接切换字符串。
// type is-a String
switch(type) {
case "AD": return new ADCommunicator();
case "DB2": return new DB2Communicator();
case "MYSQL": return new MYSQLCommunicator();
default: return null;
}
切换枚举将与 map 一样快,如果不是更快的话。打开字符串将与 map 一样快。
或者有一张工厂 map :
private final static Map<String, Factory<? extends Communicator>> map;
static {
map.put("AD", ADCommunicatorFactory.getInstance());
//...
map.put(null, NullFactory<Communicator>.getInstance());
} // populated on class-load. Eliminates race from lazy init
// on get
return map.get(type).make();
或者使用反射 API 来创建实例,但是使用条件可能会更好。
// on init
Map<String, Class<? extends Communicator>> map = new HashMap<>();
map.put("AD", ADCommunicator.class);
// on get
try {
return (Communicator) map.get(type).newInstance();
} catch(InstantiationException | IllegalAccessException | NullPointerException e) {
return null;
}
附言这听起来像是过早的优化。我怀疑确定使用哪个 Communicator 会成为您系统中的瓶颈。
关于java - 多个线程在单例类中使用相同对象的影响,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47756329/
我是一名优秀的程序员,十分优秀!