我看到有人在编写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();
}
}
反对这样的设计(使每个方法静态化)的论点是什么?
这基本上是"全局变量"的一种变体,问题总是相同的:您只能有一个。如果您需要替换或扩展它,很多代码都会中断。
为什么其他日志记录框架使用工厂:
private final static Logger log = LoggerFactory.getLogger( Foo.class );
这样,我只有一个全局变量(而不是您的数十个变量)。这不是理想的方法,但至少会给我一个失败点。
这种方法允许我用几乎所有内容扩展/替换Logger接口,而不必更改代码中的数百个位置。
就是说:不要编写自己的日志记录API。使用slf4j。您将需要花费更长的时间来了解它的工作原理,但是许多聪明的人花了多年的时间来构建一个出色的日志记录框架,以解决您尚不了解的数千个问题。
编辑
its not ecactly a general loging util. but more a"Reporter class" which produces Business Word documents.
然后看看静态导入。
我建议公开一个单一的getInstance()方法,但给该方法一个更有用的名称。然后,您可以在其他任何地方静态导入此单个方法,并在不带LogUtil.前缀的情况下调用它。
实际上,它并不是一般的日志实用程序。但是更多的是" Reporter类",它可以生成Business Word文档。作者认为,此LogUtil类永远不会扩展或重构。作者只是想尽可能简化调用客户端代码的用法。也永远不会有任何线程问题
作者如果有错。实际使用的每个程序最终都需要扩展和重构。不要用脚射击未来的人(或将来要维护自己的代码的人)来节省几分钟的时间。
@jack:这是一种用于结构化编程的方法(在OO之前我们有过)。 Java作为一种面向对象的语言,在摆脱所有面向对象的东西时有些僵化。我建议公开一个getInstance()方法,但给该方法一个更有用的名称。然后,您可以在其他任何地方静态导入此单个方法,并在不带LogUtil.前缀的情况下调用它。
使方法静态化的一种经验法则是:问自己"即使尚未构建Obj,调用此方法是否有意义?"如果是这样,那肯定是静态的。"
在您的示例中,诸如logSomething(),anotherMethod()之类的操作正在对实例进行处理。由于这些方法没有实例是没有意义的,因此它们应该是非静态的。只有getInstance()方法应该是静态的。
使所有内容保持静态的主要缺点是您无法在运行时交换,覆盖或选择方法实现。该线程对静态的缺点进行了很好的讨论:在Java中,类上的静态方法是否有缺点?
该类的作者可能想构建一个流畅的接口,解释为什么getInstance对于其他类的方法调用将被隐藏,并解释返回类型不为空。
这样做的好处是可使客户端使方法调用更简洁:
LogUtil.init().logSomething("something").anotherMethod("text");
这样整体减少到一行。
我不处理"静态"辩论,因为正如Aaron上面所述,static通常经常不被推荐,因为它破坏了灵活性/可扩展性并且是抗OO。
没错,作者真的更喜欢流畅的界面。他辩称,如果您必须一遍又一遍地执行此操作,那么必须调用LogUtil.getInstance()就是很多。
对于那些承认静态方法是一个不错的选择的人...没错。对于其他人来说,创建一个为特定类返回特定日志实例的工厂更为关注OO。
静态类是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并返回它,该Logger具有实例方法,例如log4j,您可以拥有ConsoleLog,FileLog,RemoteLog等。