【发布时间】:2017-12-11 15:38:41
【问题描述】:
我正在设计一个可以支持不同数据源的模块。 我的模块获取用户的公司 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”是一个接口,通信器映射会返回相应的实例。 这是同一个单例类中的 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 接口。
该代码似乎在我的测试草稿中有效。 我唯一担心的是 HashMap 将为所有相同类型的通信请求返回相同的对象。如果我想避免条件语句,我似乎无法避免在哈希图中使用相同的实例。否则,我可以像这样调用而不是 hashmap。
Communicator comm;
if (type = "AD") comm = new ADCommunicator();
if (type = "DB2") comm = new DB2Communicator();
if (type = "MYSQL") comm = new MYSQLCommunicator();
我通过使用 hashmap 根据类型返回一个实例来避免这种情况。 但是我无法避免获得相同实例的单例问题。
在需要一次支持数十万个通信请求的多线程环境中,考虑到我需要在每个 Communicator 类中同步大量代码,这可能是个问题。 有没有办法可以避免同步并使其线程安全而不影响性能?
【问题讨论】:
-
您还可以有一个工厂工厂,其中地图中的值是您的实际
Communicator实例的工厂。它将被委派给CommunicatorFactorys 来选择是返回单例Communicator还是按需返回新实例,或者介于两者之间。 -
不要懒惰地填充哈希图,只需在静态块中一劳永逸地填充它(并确保在初始化后永远不会访问它)。那么只要 XxxCommunicator 类是线程安全的,你就可以了。
-
旁注,
if (communicatorMap.containsKey(dataSourceType)) return communicatorMap.get(dataSourceType); return null;与return communicatorMap.get(dataSourceType);一模一样。 -
> “我唯一担心的是 HashMap 将为所有相同类型的通信请求返回相同的对象。”我很困惑,您是否想要源的单个实例?
-
@dozer 不,我的意思是一个静态块:
static { /* intialise the map */ }在你的班级。不是静态方法。
标签: java multithreading design-patterns singleton