我有0..n个对象,每个对象都需要一个以这种方式创建的唯一标识符:
public class Squirrel {
private static numSquirrels = 0;
private String id = null;
public Squirrel() {
this(String.valueOf(numSquirrels++);
}
public Squirrel(String id) {
this.id = id;
}
}
这在几个方面是个问题,但我会给出一个:
当单元测试时,numSquirrels变量在其间进行 测试,即使我可能与不同的人口一起工作 松鼠。这意味着我的ID会继续增加 喜欢重新开始。
答案 0 :(得分:3)
我认为这个实现可以正常工作,但如果你正在处理并发性,你应该使用AtomicInteger。
您的单元测试问题可以使用模拟和将其包装在另一个类中进行模拟来解决。看这篇文章 How to mock a static variable in java using JMock
或者,一个简单的解决方案是为静态变量公开一个setter,在测试用例结束时,你可以将它设置为0,或者“reset”对你意味着什么。
答案 1 :(得分:0)
引入一个名为SquirellPopluation
的类,它将作为Squirrel工厂,将静态计数器移动到它,并使其成为实例变量。
如果您希望工厂用户能够设置自己的ID,那么请使用集合而不仅仅是计数器。
答案 2 :(得分:0)
您可以为该类设置静态“重置”方法。将其称为测试拆除(或设置)的一部分。
答案 3 :(得分:0)
松鼠班应该不了解工厂。我建议以下实施:
public interface Squirrel // interface, not class
{
public String getID ();
// other methods here
}
public class SquirrelFactory
{
private int nextSquirrelID = 0;
public Squirrel createSquirrel ()
{
return new SquirrelImpl (String.valueOf (nextSquirrelID++));
}
private static class SquirrelImpl implements Squirrel
{
private final String id;
// other fields here
public SquirrelImpl (String id)
{
this.id = id;
}
@Overrides
public String getID ()
{
return id;
}
// other methods here
}
}
然后使用createSquirrel
的方法SquirrelFactory
而不是构造函数。对于每个单元测试,创建SquirrelFactory
类的新实例。
答案 4 :(得分:0)
只是与上一个问题相关的特定案例:
如果我希望用户能够设置ID(或至少建议ID),我如何确保唯一性?
如果要执行此操作,则必须跟踪所有实例。例如,您可以使用BitSet
。如果你这样做,你就会提供一种解构器:
/**
* Eat the squirrel.<br>
* You can not do anything anymore with the squirrel after it has been eaten,
* but it can be reborn.
*/
public void eat() { //at least, sounds friendlier than kill, shoot, or whatever
instances.clear(id);
}
要小心,因为这不是像c ++那样真正的解构器。你不能(轻易地)摧毁这个物体。它仍然可以使用。你应该在内部处理这个问题。
提示:如果使用多线程代码,实时开始变得复杂。但显然来自静态id,你没有。
答案 5 :(得分:0)
我认为为了满足您的所有要求,您需要一个SquirrelFactory类来获取新的ID并确保它们都是独一无二的。您可能希望将SquirrelFactory变为单身人士。
SquirrelFactory的责任是: