java - 面向对象设计和在抽象父类(super class)中初始化静态成员

标签 java inheritance concurrency static

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

现在我有 3 个疑问:

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

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

3.) 在静态 block 内初始化静态成员(hashmap)是否错误?因为我的老板非常反对使用静态成员和 block 。那么,如果我在静态 block 内初始化此映射,可能会出现什么问题?

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/third 以及相应的 SubCallableOne/two/third。

最佳答案

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

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

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

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

3)这本身并没有错,但静态是众所周知的代码味道。这使得类很难测试。并且不能被覆盖。在纯面向对象设计中,不需要静态。在您的情况下, map 将在第一次加载类时初始化,因此任何对 AbSuper.getMap 的调用将填充 map 。但是您的 map 有两个问题。第一个是,这通常不适合进行长时间操作(例如从文件填充 map )。您应该使长操作显式化,不要将它们隐藏在构造函数或静态初始值设定项中。第二个是 map 是可变的。

关于java - 面向对象设计和在抽象父类(super class)中初始化静态成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32414069/

相关文章:

java - 使用 GSON 将 JSON 文件中的数据解析为 Java 对象

java - 继承泛型

go - 追加不是线程安全的?

java - 在 Java EE 应用程序中使用 hibernate

java - 带有 Spring 4 注解的 404 错误页面配置

oop - Racket 子类中绑定(bind)的自动继承

Java 重写私有(private)与公共(public)

java - JMM 中的执行和因果关系要求

java - 如果在数据检索过程中删除记录会发生什么?

java - 在我的类中传递/赋值时出现 NullPointerException