【问题标题】:Logic in constructor?构造函数中的逻辑?
【发布时间】:2014-06-04 13:34:01
【问题描述】:

下面的代码运行良好,但我想知道对象创建时间是否有任何问题。

import java.util.Scanner;

public class FactorialExample {
    public FactorialExample(int n) {
        int fact=1;
        for(int i=1;i<=n;i++) {
              fact=fact*i;  
        }
        System.out.println("the factorial of a given number is::"+fact);        
    }
            public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        System.out.println("Enter any Integer Value:");
        int value=sc.nextInt();
        FactorialExample fe=new FactorialExample(value);

    }
}

【问题讨论】:

  • 构造函数多用于初始化变量。
  • 也许适合这个问题的论坛是codereview.stackexchange.com
  • 首先,你的计算会很快溢出int。其次,我推荐一个memoization 优化。最后,“factorail”是“factorial”。
  • 这个问题似乎是题外话,因为它是关于代码审查的。可能更适合codereview.stackexchange.com

标签: java


【解决方案1】:

是的,你的假设是正确的——不要在构造函数中使用业务逻辑。

最多初始化对象状态。

否则,异常处理、测试和模拟等事情可能会变得困难。

实际上,在您的代码中,您可以完全避免使用构造函数:

import java.util.Scanner;

public class FactorialExample {
    int solve(int n){
        int fact=1;
        for(int i=1;i<=n;i++){
            fact=fact*i;
        }
        return fact;
    }

    public static void main(String[] args) {
        FactorialExample fe=new FactorialExample();
        Scanner sc=new Scanner(System.in);
        System.out.println("Enter any Integer Value:");
        int value=sc.nextInt();
        int solution = fe.solve(value);
        System.out.println("tha factorail of a given number is::"+solution);
    }
}

【讨论】:

  • 为什么要构造一个没有状态的对象的实例来调用计算方法?
  • Tetsujin,你之前编辑了我的答案,我拒绝了你的编辑。没有充分理由(工厂类等)使用静态上下文是非常糟糕的做法。静态代码更难正确测试和调试。当然,这是一个简单的例子,但我们不要养成坏习惯
  • 也可以使用构造函数来初始化事件吗?例如在js中初始化所有的点击。
  • @RalphDingus js 有点像狂野的西部——普通的面向对象的企业语言原则并不总是适用;)
【解决方案2】:

构造函数只能用于初始化对象的状态/字段。 您应该将其他事情的责任委托给其他方法。 请注意,构造函数只被调用一次,即每当您创建一个新对象时。在这里,在您的设计中,如果不创建 FactorialExample 的对象,就无法计算数字的阶乘。相反,您应该在 FactorialExample 中添加一个数字 n 作为字段,并使用单独的方法计算阶乘。

【讨论】:

  • >构造函数只能用于初始化对象的状态/字段。为什么?
【解决方案3】:

是的。如果输入足够大,您可能会在构造函数中引发异常。

这是您不应该使用构造函数来包含“业务逻辑”的几个原因之一。

在这种情况下,使用构造函数来执行计算和执行输出与良好做法完全背道而驰:

  • 您有一个不包含任何状态且仅在其构造函数中起作用的对象。
  • 您没有与构造函数创建的对象进行交互,部分原因是它没有可与之交互的方法或字段。
  • 如果将您的构造函数视为方法,则违反了方法应具有单一目的(通过执行计算和执行输出)的原则。

【讨论】:

  • 顺便说一句,我把他从任何 OOPC 书籍的第 1 章到第 5 章拿来
【解决方案4】:

这是一个问题,在这种情况下,您要与现实世界的问题域一起尝试实现什么是阶乘。

如果构造函数拥有一切,那么构造函数就知道许多其他对象。 它变得依赖于所有这些对象。

添加功能时:

示例:如果我想要员工可以围坐在桌子旁的所有位置怎么办。上面的类将无法创建,因为它过于依赖创建。

因此,您将不得不扩展您的域以包含重载的构造函数,并且很快您就会意识到随着依赖项和域特定对象数量的增加,它变得无法维护。

将其拆分是最佳编程实践。

领域驱动设计中提出的服务概念。 现在最好阅读不同的设计模式,尤其是 http://en.wikipedia.org/wiki/Design_Patterns#Creational

工厂以及我们使用它们的原因 在不指定确切的对象类的情况下创建对象的问题 http://en.wikipedia.org/wiki/Factory_method_pattern

然后我会建议继续阅读依赖注入和控制反转以及它为什么/如何解耦代码。

http://martinfowler.com/articles/injection.html

希望这会有所帮助!

【讨论】:

  • 你是如何从这个问题中进入 IoC 的?
  • 如果你耐心地阅读完整的段落,你会发现它只是为了阅读和建立理解而被提及......干杯......
  • 我阅读了您的全部答案;我建议尝试对其进行编辑以清楚地解决这个问题,而不是立即启动 DI/IOC 和工厂方法。
  • 我认为最好将它原封不动地留给更多的观众,因为它会回答并导致进一步的探索。在我匆忙进行编辑之前让社区决定路线:)
【解决方案5】:

在您的情况下,fact 是构造函数内的局部变量。它甚至不在构造函数之外使用。所以在这种情况下不应该使用构造函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-05
    • 2021-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-11
    • 1970-01-01
    相关资源
    最近更新 更多