关于java:所有静态方法还是单个实例?

All static methods or a single instance?

有时,由于集合的存在,我会想出一个类的单个实例足够的情况。例如,我的解码器类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Decoder
{

    private static final Decoder instance = new Decoder();
    private final HashMap<Client, State> states = new HashMap<Client, State>();

    private Decoder()
    {

    }

    public Packet decode(Client client, ByteBuffer data)
    {
            return null;
    }
}

但我在想,为什么不让它看起来像:

1
2
3
4
5
6
7
8
9
10
public class Decoder
{

    private static final HashMap<Client, State> states = new HashMap<Client, State>();

    public static Packet decode(Client client, ByteBuffer data)
    {
            return null;
    }
}

两种设计有效地完成了相同的事情。这两者有什么实际区别吗?我什么时候用一个比另一个?谢谢。


如果要对使用Decoder对象(或任何其他"实用程序"对象)的类进行单元测试,您可能需要模拟它——也就是说,将Decoder替换为行为已知的虚拟对象。这样,如果Decoder类发生更改,您的单元测试就不会中断。

如果Decoder是一个实际对象,这就容易实现了。如果Decoder是一个充满静态方法的类,您就不能真正轻松地模拟它(尽管有一些模拟框架可以通过使用字节代码来实现这一点)。

总之,静态方法是一种可测试性反模式。我强烈建议不惜一切代价避免使用它们。如果你想了解更多关于这方面的信息,请访问http://misko.hevery.com/2008/12/15/static-methods-are-death-to-testability/-在这个网站上还有很多关于可测试性的好建议。


我将使用所有静态方法,除非您看到需要实现接口,例如,这样您就可以模拟或替换实例。

1
2
3
4
5
6
7
8
9
public enum Decoder implements IDecoder {
    INSTANCE;

    private final Map<Client, State> states = new HashMap<Client, State>();

    public Packet decode(Client client, ByteBuffer data) {
            return null;
    }
}

1
2
3
4
5
6
7
public enum Decoder {;
    private static final Map<Client, State> states = new HashMap<Client, State>();

    public static Packet decode(Client client, ByteBuffer data) {
            return null;
    }
}


我认为在客户端类中编写代码时,使用静态方法要短一些,

1
2
3
4
5
6
7
8
9
public class Collections {
   // Suppresses default constructor, ensuring non-instantiability.
   private Collections() {
   }

   public static <T extends Comparable<? super T>> void sort(List<T> list) {
       ...
   }
}

然后我们有,

1
Collections.sort(list);