有7-8个类(实现可调用的)具有一些类似的行为,即它们具有一些具有类似实现的类似功能。并且所有这些都使用HashMap(仅用于阅读目的),这对于所有这些类都是相同的。 所以我决定创建一个包含所有类似方法的抽象超类加上这个hashMap作为静态成员。 我将为这些7-8个可调用类创建子类(因此这些类也可以通过继承调用),这样可以提高app的性能。
现在我有3个查询:
1。)这个设计中是否有任何缺陷,我是否可以进一步改进它?
2。)是否会出现任何并发问题,因为它是一个三级层次结构,在底部两个级别具有可调用类?
3.。)在静态块内初始化静态成员(hashmap)是错误的吗?因为我的老板痴迷于使用静态成员和块。那么如果我在静态块中初始化这个映射会出现什么问题?
public abstract class AbSuper {
private static HashMap hmap;
private static CompletionService<String> service;
private static int maxThreads = 10;
static{
initializeMap();
}
public static void initializeMap(){
//load from file
}
public HashMap getmap(){
return hmap;
}
public void commonMethodOne(){
//do something
}
public static CompletionService<String> getService(){
ExecutorService executor = Executors.newFixedThreadPool(maxThreads);
service = new ExecutorCompletionService<String>(executor);
return service;
}
}
public class CallableOne extends AbSuper implements Callable<String>{
private List<String[]> taskList;
protected HashMap resultMap;
public List<String[]> getTaskList(){
return taskList;
}
public String call(){
for(String[] task : getTaskList()){
getService().submit(new SubCallableOne(task));
}
return "done with Callable One";
}
}
public class SubCallableOne extends CallableOne {
String[] task;
public SubCallableOne(String[] task) {
this.task = task;
}
public String call(){
//do what you are suppose to do
//and then access and populate "resultMap" fom superclass
return "done with subCallableOne";
}
}
将有7-8 CallableOne / two / 3和相应的SubCallableOne / two / 3。
答案 0 :(得分:2)
1)你真的需要使用静态成员吗?如果是这样,也许你应该将它封装在一个单独的类中,并通过封装而不是继承来使用它。我仍然使用常用方法保留一个超类。
但无论如何,您当前的代码存在问题。即:
AbSuper.getMap
公开地图,并且它是可变的。任何代码都可以添加,删除或覆盖条目。它真的应该公开吗?看起来只有子类正在使用它。如果是这样,您可以使其受到保护并返回只读地图或副本,或者创建受保护的函数readFromMap(key)
。AbSuper.getService
方法相同:它是公共的和静态的。任何类中的任何代码都可以提交任务或关闭它。除非您每次都创建一个新的执行程序。这可能是一个错误,因为每次调用getService
都会覆盖service
变量。看起来你试图在这里实现单身但失败了。2)可调用类可能是底层的类,但是由于公共静态方法,您将基类中的功能暴露给程序中的每个其他类,以及由于公共方法而持有实例的任何人。即使这些方法不存在,所有实例使用共享映射和执行程序服务的事实都可能导致意外的副作用。例如,提交任务的执行顺序。
3)这本身并没有错,但静态是众所周知的代码味道。它使类难以测试。并且无法覆盖。在纯OO设计中,不需要静力学。在您的情况下,地图将在第一次加载类时初始化,因此对AbSuper.getMap
的任何调用都将填充地图。但是你的地图有两个问题。第一个是,这通常不适合长时间操作,例如从文件填充地图。您应该将长操作显式化,不要将它们隐藏在构造函数或静态初始化器中。第二个是地图是可变的。