2

我的一般问题是何时将争论传递给构造函数,何时将争论传递给类的方法。一般来说,对象是“数据”+“作用于数据的方法”。

我有几个选择来设计一个名为 DFS 的类。以下哪个示例套件定义最好?

选项1:在构造函数中传递图形,在函数中传递源。Adv:相同的 DFS 对象将被不同的源重用。

public class DFS {
   Graph g;
   public DFS(Graph g) {
     this.g = g;
   }

   public void doDfs(int source) {
     // dfs computation
   }
}

选项 2:具有 2 个参数且没有多态性的构造函数 缺点:对于每个新源,都需要构造新对象。

public class DFS {
    Graph g;
    int source;   

    public DFS(Graph g, int source) {
      this.g = g;
      this.source = source;
    }

    public void doDfs() {
      // dfs computation
    }
 }

选项 3:重载构造函数 Adv:解决我们所有的用例。Dis:多态性是昂贵的。

public class DFS {
   Graph g;
   int source;   

   public DFS(Graph g) {
     this.g = g;
   }

   public DFS(Graph g, int source) {
     this.g = g;
     this.source = source;
   }

   public void doDfs() {
      doDfs(source);
   }

   public void doDfs(int source) {
     // dfs computation
   }
}

选项 4:没有构造函数

public class DFS {

    DFS() { }

    public void doDFS(Graph g, int source) {
      this.g = g;
      this.source = source;
      // dfs computation
    }
 }
4

3 回答 3

2

当你有一些与类的操作/定义相关的东西时,它意味着作为构造函数传递。这也意味着,非常希望将其作为immutable. 例如:

public class DFS {
   final Graph g;
   public DFS(Graph g) {
     this.g = g;
   }

   public void doDfs(int source) {
     // dfs computation
   }
}

在这里,您知道该类DFS包含多个方法(每个方法都有自己的算法)来查找DFS图形g。在这种情况下,您知道这g是不可变的,并且为每个方法调用传递它会很痛苦,因此最好将其设为构造函数参数。一些优点:

  1. 每个方法调用都没有多余的参数。
  2. 如果你想做一些内部缓存,你可以这样做。这是因为一切都与已知实体相关:g
  3. 线程安全,无显式锁定。你会需要它与二传手。

简而言之,当您知道某些内容不会更改为类的定义时,请将其作为构造函数参数。拥有使用这些实例变量的方法。当您知道某些事情可以改变时,请使用 Setters。

于 2013-08-05T06:51:26.430 回答
0

这是一个逻辑问题。当您设计了类以使类的对象需要特定数据才能有效时,则必须在构造函数中提供数据。您还应该检查对象是否实际上是通过 using 传递的assert

但是您可以选择设计您的类,以便稍后添加数据。这取决于你打算如何使用你的类——你应该为它的用户设计你的类。

顺便说一句,您在帖子中评论说“多态性很昂贵”。不,如果多态性可以为您完成工作,那么它并不昂贵。这也取决于您的意思是哪种多态性。

于 2013-08-05T07:01:21.943 回答
0

就我个人而言,我更喜欢选项 4。没有构造函数或最小构造函数使得使用单元测试来测试类变得更加容易。

同样在较大的项目中,我更喜欢创建只包含参数的新类,然后使用这样的类作为参数。如果多次传递相同的参数,则以后在不更改所有方法的情况下进行更改会变得更加容易。

于 2013-08-05T07:02:06.227 回答