【问题标题】:OO design and Initializing Static members in Asbtract Super classAsbtract Super 类中的 OO 设计和初始化静态成员
【发布时间】:2015-09-05 14:15:24
【问题描述】:

有 7-8 个类(可调用的实现)具有一些相似的行为,即它们具有一些具有相似实现的相似功能。而且所有这些都使用了所有这些类都相同的 HashMap(仅用于阅读目的)。 所以我决定创建一个抽象超类,包含所有类似的方法加上这个 hashMap 作为静态成员。 我将为这 7-8 个可调用类创建子类(因此这些类也可以通过继承调用),以便提高应用程序的性能。

现在我有 3 个查询:

1.) 这个设计有什么缺陷吗?我可以进一步改进它吗?

2.) 是否会出现任何并发问题,因为它是一个三层层次结构,可调用类位于底部两层?

3.) 在静态块中初始化静态成员(哈希图)是否错误?因为我的老板非常反对使用静态成员和块。那么如果我在静态块中初始化这个地图会出现什么问题呢?

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/二/三和它们对应的SubCallableOne/二/三。

【问题讨论】:

标签: java inheritance concurrency static


【解决方案1】:

1) 你真的需要使用静态成员吗​​?如果是这样,也许您应该将其封装在一个单独的类中,并通过封装而不是继承来使用它。我仍然会使用常用方法保留一个超类。

但无论如何,您当前的代码存在问题。即:

  • 您正在通过公共方法AbSuper.getMap 公开地图,它是可变的。任何代码都可以添加、删除或覆盖条目。真的应该公开吗?看起来只有子类在使用它。如果是这样,您可以将其设为受保护并返回只读映射或副本,或者创建一个受保护的函数readFromMap(key)
  • AbSuper.getService 方法也一样:它是公共的和静态的。任何类中的任何代码都可以提交任务或关闭它。除非您每次都创建一个新的执行程序。这可能是一个错误,因为每次调用getService 都会覆盖service 变量。看起来您试图在这里实现单例但失败了。

2) 可调用的类可能位于底部,但是由于公共静态方法,您将基类中的功能暴露给程序中的每个其他类,并且由于公共方法而对持有实例的任何人开放。即使这些方法不存在,您的所有实例都使用共享地图和执行程序服务这一事实也可能导致意外的副作用。比如提交任务的执行顺序。

3) 这本身并没有错,但静态是众所周知的代码气味。它使类难以测试。并且不能被覆盖。在纯 OO 设计中,应该不需要静态。在您的情况下,地图将在第一次加载类时被初始化,因此任何对 AbSuper.getMap 的调用都会填充地图。但是你的地图有两个问题。第一个是这通常不适合长时间的操作,比如从文件中填充地图。您应该明确长操作,不要将它们隐藏在构造函数或静态初始化程序中。二是地图是可变的。

【讨论】:

    猜你喜欢
    • 2011-07-18
    • 2015-05-18
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 2013-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多