1

有时,由于集合,我会遇到一个类的单个实例就足够的情况。一个例子是我的解码器类:

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;
    }
}

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

public class Decoder
{

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

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

两种设计都有效地完成了同样的事情。两者有什么实际区别吗?我什么时候会使用其中一个?谢谢。

4

3 回答 3

3

如果您想对使用 a Decoder(或任何其他“实用程序”对象)的类进行单元测试,您可能希望将其模拟出来 - 即,将 替换为Decoder行为已知的虚拟对象。Decoder这样,如果类发生变化 ,您的单元测试不会中断。

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

简而言之,静态方法是一种可测试性反模式。我强烈建议不惜一切代价避免它们。如果您想了解更多关于此的信息,请尝试http://misko.hevery.com/2008/12/15/static-methods-are-death-to-testability/ - 此站点上还有很多其他关于可测试性的好建议也。

于 2012-04-28T05:46:20.360 回答
1

我认为在客户端类中编码时使用静态方法更短,

public class Collections {
   // Suppresses default constructor, ensuring non-instantiability.
   private Collections() {
   }

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

然后我们有,

Collections.sort(list);
于 2012-04-28T05:40:56.897 回答
1

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

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;
    }
}

或者

public enum Decoder {;
    private static final Map<Client, State> states = new HashMap<Client, State>();

    public static Packet decode(Client client, ByteBuffer data) {
            return null;
    }
}
于 2012-04-28T07:38:35.620 回答