Напишите класс Java, чтобы создать только пять его экземпляров - PullRequest
3 голосов
/ 03 августа 2010

Я хочу написать Java-класс, который может быть создан только 5 раз, точно так же, как у вас есть синглтон-класс, у которого есть только один экземпляр.

Кроме этого, экземпляры должны выбираться на основе циклического перебора.

Предположим, у меня есть класс А. Я должен иметь возможность создать только 5 экземпляров этого класса. Скажем, у меня есть экземпляр A_1, экземпляр A_2, экземпляр A_3, экземпляр A_4, экземпляр A_5. Всякий раз, когда мне нужно использовать их, они должны быть выбраны на основе круговой системы.

Ответы [ 10 ]

14 голосов
/ 03 августа 2010

Так же, как enum рекомендуется Effective Java 2nd Edition для реализации синглтона, в этом решении также используется enum для реализации ... четверки?

import java.util.*;

public enum RoundRobin {
    EENIE, MEENIE, MINY, MO;

    private final static List<RoundRobin> values =
        Collections.unmodifiableList(Arrays.asList(values()));
    // cache it instead of creating new array every time with values()

    private final static int N = values.size();
    private static int counter = -1;

    public static RoundRobin nextInstance() {
        counter = (counter + 1) % N; // % is the remainder operator
        return values.get(counter);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            System.out.println(RoundRobin.nextInstance());
        }
        // EENIE, MEENIE, MINY, MO, EENIE, MEENIE, MINY, MO, ...
    }
}

Расширение этогок пятерке не требует объяснений.

См. также

  • Effective Java 2nd Edition, свойство Enforce singleton с помощью частного конструктора или тип перечисления

    Начиная с версии 1.5., Существует третий подход к реализации синглетонов.Просто создайте тип enum с одним элементом.Этот подход функционально эквивалентен подходу открытого поля, за исключением того, что он более лаконичен, предоставляет механизм сериализации бесплатно и обеспечивает железную гарантию от множественных реализаций, даже перед сложными атаками сериализации или отражения.Хотя этот подход еще не получил широкого распространения, одноэлементный тип перечисления является лучшим способом реализации одноэлементного .

Смежные вопросы

2 голосов
/ 03 августа 2010

Вам нужно что-то вроде пула объектов .Самой простой реализацией было бы иметь синглтон, содержащий List из 5 объектов, и всякий раз, когда вы вызываете getInstance(..), список должен повторяться и возвращаться один из объектов.

1 голос
/ 03 августа 2010

Я полагаю, что все, что вам нужно сделать, это расширить шаблон Singleton для использования счетчика. Что-то вроде ...

// Declare a list holding the 5 Objects
List<Foo> instances = new ArrayList<Foo>(5);
// Keep track of which Object you are returning next
int curr = 0;

...

static Foo getInstance() {
    // Only instantiate when necessary
    if (instances.get(curr) == null) {
        instances.set(curr, new Foo());
    }
    Foo toReturn = instances.get(curr);
    // Use modulus to loop back to 0 after 4
    curr = (curr + 1) % 5;
    return toReturn;
}

Отказ от ответственности: я предполагаю, что вам не нужен код, чтобы быть потокобезопасным.

1 голос
/ 03 августа 2010

Ну, что-то в этом роде:

  • Сделать конструктор приватным
  • Создайте пять экземпляров в статическом инициализаторе и сохраните ссылки в массиве
  • Сохранить индекс для указания следующего, который нужно вернуть
  • Напишите статический метод для возврата следующего значения и увеличения индекса.

Чтобы быть потокобезопасным, вам нужно заблокировать в статическом методе. Вы можете использовать AtomicInteger, но упаковка сложна. Вы всегда можете использовать AtomicInteger или AtomicLong, увеличивать каждый раз и индексировать с помощью оператора% ... но когда индекс обернут, вы получите разрыв. Это может или не может быть проблемой для вас.

(Предполагается, что вы не против создать все пять экземпляров заранее. Это, безусловно, облегчает задачу.)

1 голос
/ 03 августа 2010

Будет ли работать пул (например, Apache Commons Pool )?

1 голос
/ 03 августа 2010

Это домашняя работа?

Почему бы вам не создать Фабрику, которая создает 5 экземпляров и хранить их в списке?Когда кто-то вызывает Factory.getInstance (), он получает правильный экземпляр, используя правильный индекс списка.

0 голосов
/ 03 августа 2010

Упрощенный RoundRobin.

import java.util.*; 

public enum RoundRobin { 
    EENIE, MEENIE, MINY, MO; 

    private final static RoundRobin[] values = values(); 
    private static int counter = -1; 

    public static RoundRobin nextInstance() {
        counter = (counter + 1) % values.length;
        return values[counter]; 
    } 

    public static void main(String[] args) { 
        for (int i = 0; i < 10; i++) 
            System.out.println(RoundRobin.nextInstance()); 
        // EENIE, MEENIE, MINY, MO, EENIE, MEENIE, MINY, MO, ... 
    } 
} 
0 голосов
/ 03 августа 2010
 class OnlyFiveTime {

    private static LinkedList<OnlyFiveTime> instaces = new LinkedList<OnlyFiveTime>();
    private static final int count = 5;

    public static OnlyFiveTime getInstace() {


        if(instaces.size() != count) {
            instaces.addLast(new OnlyFiveTime());
        }

        OnlyFiveTime robinRound = instaces.removeFirst();

        instaces.addLast(robinRound);

        return robinRound;

    }

    private OnlyFiveTime() {

    }

}
0 голосов
/ 03 августа 2010

Вот очень упрощенное решение.Обратите внимание, что это не потокобезопасно:

class ClassA {

    private final List<ClassA> instances = Arrays.asList(new ClassA(), new ClassA(), new ClassA(), new ClassA(), new ClassA());

    private ClassA() {}

    public static ClassA getInstance() {
        Collections.shuffle(instances);
        return instances.get(0);
    }

}
0 голосов
/ 03 августа 2010

Создайте пять статических экземпляров. Держите индекс последней инстанции. Сделай приватный конструктор. Используйте метод для получения экземпляра (аналог одиночного);

public class MyObject {

private static final MyObject instance_1 = new MyObject();
private static final MyObject instance_2 = new MyObject();
private static final MyObject instance_3 = new MyObject();
private static final MyObject instance_4 = new MyObject();
private static final MyObject instance_5 = new MyObject();

private static final MyObject[] instances = new MyObject[]{instance_1, instance_2,instance_3, instance_4,instance_5};

private MyObject() {

}

private static volatile int index = 0; //in a multi-threaded evironment, you should use volatile

    /**
     * The following code is not thread safe
     */
public static MyObject getInstance() {
    MyObject instance = instances[index];

            if (index == 4) {
                index = 0;
            } else {
                index++;
            }
    return instance;
}

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...