【问题标题】:How-to create a static java API?如何创建静态 Java API?
【发布时间】:2013-10-18 09:28:18
【问题描述】:

我看到有人写了一个 java LOG API,就像下面的代码一样。 这个想法是客户端不必每次都调用 LogUtil.getInstance()。 但我的感受是这不是惯用的java吗?

public class LogUtil{
private static LogUtil instance;
private Object current;//some Logger
private static LogUtil getInstance(){
    if(instance == null){
        instance = new LogUtil();
    }
    return instance;
}

private static void debug(String text){

}

public static LogUtil init(){
    //dosomething with
    // getInstance().current;
    return getInstance();
}

public static LogUtil logSomething(String text){
    //dosomething with
    // getInstance().current;

    return getInstance();
}
public static LogUtil anotherMethod(String text){
    //dosomething with
    // getInstance().current;

    return getInstance();
}

}

反对这种设计(使每个方法都是静态的)的论据是什么?

【问题讨论】:

    标签: java


    【解决方案1】:

    这基本上是“全局变量”的变体,问题总是一样的:你只能拥有其中一个。如果您需要替换或扩展它,很多代码都会中断。

    为什么其他日志框架使用工厂:

     private final static Logger log = LoggerFactory.getLogger( Foo.class );
    

    这样,我有一个全局变量(而不是你的情况下的几十个)。这并不理想,但至少给我一个单点故障。

    这种方法允许我用几乎任何东西扩展/替换Logger 接口,而无需更改代码中的数百个位置。

    也就是说:不要编写自己的日志记录 API。使用slf4j。您可能需要更长的时间才能理解它是如何工作的,但是许多聪明人已经花费了数年时间来构建一个出色的日志记录框架,该框架可以解决数千个您还不知道的问题。

    编辑

    它并不是一个通用的日志工具。但更多的是产生商业Word文档的“记者类”。

    然后看看静态导入。

    我建议公开一个getInstance() 方法,但给该方法一个更有用的名称。然后,您可以在其他任何地方静态导入这个单一方法,并在没有 LogUtil. 前缀的情况下调用它。

    【讨论】:

    • 它并不是一个通用的日志工具。但更多的是产生商业Word文档的“记者类”。作者认为永远不会对这个 LogUtil 类进行扩展或重构。作者只是想让调用客户端代码的使用尽可能简单。也永远不会有任何线程问题
    • 作者如有错误。每个实际使用的程序最终都需要扩展和重构。不要通过射击未来的你(或未来的员工来维护你的代码)来节省几分钟。
    • @jack:这是一种用于结构化编程的方法(我们在 OO 之前就有这种方法)。 Java,作为一种面向对象的语言,在摆脱所有面向对象的东西时有些不灵活。我建议公开一个 getInstance() 方法,但给该方法一个更有用的名称。然后,您可以在其他任何地方静态导入这个单一方法,并在没有 LogUtil. 前缀的情况下调用它。
    【解决方案2】:

    静态类是 Helper 类,对于您的 LogUtil 静态类,我将声明所有方法以返回 void:

    public class LogUtil{
    private static LogUtil instance = new LogUtil(); //Initialization here
    private Object current;//some Logger
    
    private static LogUtil getInstance(){
    }
    
    private static void debug(String text){
    
    }
    
    public static void init(){
        //dosomething with
        // instance.current;
    }
    
    public static void logSomething(String text){
        //dosomething with
        // instance.current;
    }
    public static LogUtil anotherMethod(String text){
        //dosomething with
        // instance.current;
    }
    }
    

    但是我对那个设计不太满意,LogUtil 的使用是根据配置偏好创建一个 Logger,然后返回它,它有实例方法,比如 log4j 你可以有 ConsoleLog、FileLog、RemoteLog 等

    【讨论】:

      【解决方案3】:

      这个类的作者可能想建立一个fluent interface,解释为什么getInstance会被其他类的方法调用隐藏,并解释返回类型不是无效的。

      这样做的好处是允许客户端使方法调用更清晰:

      LogUtil.init().logSomething("something").anotherMethod("text");
      

      整体就这样缩成了一行。

      我不是在处理“静态”辩论,因为正如 Aaron 上面所说,static 通常通常不被推荐,因为它破坏了灵活性/可扩展性并且是反 OO 的。

      【讨论】:

      • 没错,作者真的更喜欢流畅的界面。他认为,如果您必须一遍又一遍地执行此操作数百次,则必须调用 LogUtil.getInstance()。
      • 对于那些承认静态方法是一个不错的选择的人......他是对的。对于其他人来说,为特定类创建返回特定日志实例的工厂更关注 OO。
      【解决方案4】:

      使方法静态化的一个经验法则是:问问自己“调用这个方法是否有意义,即使还没有构造 Obj?”如果是这样,它肯定应该是静态的。" 在您的示例中,诸如 logSomething()、anotherMethod() 之类的操作正在对实例执行某些操作。由于这些方法没有实例就没有意义,它们应该是非静态的。只有 getInstance() 方法应该是静态的。

      将所有内容设为静态的主要缺点是您无法在运行时交换、覆盖或选择方法实现。这个帖子很好地讨论了静态的缺点:In Java, is there any disadvantage to static methods on a class?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-01-05
        • 2022-11-12
        • 1970-01-01
        • 1970-01-01
        • 2012-01-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多