如何用Java中的工厂替换静态计数变量?

时间:2013-02-07 18:59:38

标签: java oop factory

我有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会继续增加   喜欢重新开始。

  • 这是使用SquirrelFactory的正确时间(孩子们正在讨价还价)?
  • 我应该使用依赖注入将Factory传递给Squirrel对象,还是应该将Squirrel类包含在与外界有接口的Squirrel Factory中?
  • 如果我希望用户能够设置ID(或至少建议ID),我该如何确保唯一性?

6 个答案:

答案 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的责任是:

  • 跟踪正在使用的ID
  • 使用基于计数器的新ID创建松鼠(并确保它是唯一的)
  • 创建具有给定ID的松鼠(用于从文件加载时)以及如果id已被使用,则创建一个新的上述
  • 将新松鼠的ID添加到正在使用的ID列表中。
  • 为了进行测试,您可能想要一种重置计数器和ID列表的方法
  • (可选)在移除松鼠时,有办法从列表中删除ID