Рандомный вызов метода

У меня есть 4 класса. Один класс для создания экземпляра с переменной равной 10000. Остальные три для того, чтобы эту переменную дробить. В каждом из них написан метод, который вычитает рандомное число из этих 10000. Вопрос в том? как мне сделать так, чтобы вызывался один из этих трех методов выбирался рандомно, вычитал число и следующий вызывался также рандомно, пока число не станет равно 0. Как это можно реализовать ? понятно, что делается все через цикл, главный вопрос с рандомным вызовом методов.


Ответы (1 шт):

Автор решения: Alex Rudenko
  1. Создаём интерфейс CheeseEater, с методом для кусания сыра:
interface CheeseEater {
    default void bite(Cheese cheese) {
        int bite = ThreadLocalRandom.current().nextInt(1, 101);
        cheese.eat(bite);
        System.out.println(this.getClass().getName() + " ate " + bite + "; cheese left: " + cheese.getWeight());
    }
}
  1. В классе Cheese сделаем метод для поедания оного:
@Getter
class Cheese {
    private int weight = 10_000;

    public void eat(int piece) {
        if (this.weight >= piece) {
            this.weight -= piece;
        } else { // whatever
            this.weight = 0;
        }
    }
}
  1. Заводим три класса реализующих интерфейс CheeseEater, использующих его дефолтную реализацию метода bite:
class Mom implements CheeseEater {}
class Dad implements CheeseEater {}
class Kid implements CheeseEater {}
  1. Организовываем список из поедателей, которые будут рандомно кусать сыр, пока не съедят его окончательно:
public static void main(String[] args) {

    List<CheeseEater> family = Arrays.asList(new Mom(), new Dad(), new Kid());

    Cheese cheese = new Cheese();

    while (cheese.getWeight() > 0) {
        family.get( // рандомно выбрать любого поедателя
            ThreadLocalRandom.current().nextInt(family.size()) 
        )
        .bite(cheese);
    }

    System.out.println("No cheese left");
}

Пример выполнения:

Mom ate 89; cheese left: 9911
Kid ate 38; cheese left: 9873
Kid ate 70; cheese left: 9803
Dad ate 22; cheese left: 9781
Kid ate 10; cheese left: 9771
Mom ate 95; cheese left: 9676
...
Mom ate 95; cheese left: 87
Mom ate 25; cheese left: 62
Mom ate 54; cheese left: 8
Kid ate 8; cheese left: 0

Рассмотрим случай, когда отсутствует общий интерфейс, а каждый из классов имеет свой уникальный метод для поедания сыра, и различаются к примеру объёмами поедания продукта (для простоты такие методы будут статическими):

class Mom {
    public static void nip(Cheese cheese) {
        int bite = ThreadLocalRandom.current().nextInt(10, 41);
        cheese.eat(bite);
        System.out.println("Mom nipped " + bite + "; cheese left: " + cheese.getWeight());
    }

}
class Dad {
    public static void gobble(Cheese cheese) {
        int bite = ThreadLocalRandom.current().nextInt(40, 101);
        cheese.eat(bite);
        System.out.println("Dad gobbled " + bite + "; cheese left: " + cheese.getWeight());
    }
}
class Kid {
    public static void bite(Cheese cheese) {
        int bite = ThreadLocalRandom.current().nextInt(1, 31);
        cheese.eat(bite);
        System.out.println("Kid bit " + bite + "; cheese left: " + cheese.getWeight());
    }
}

Тогда нужно завести массив/список ссылок на соответствующие статические методы которые по сути являются Consumer<Cheese>, затем выбирать рандомно в цикле нужного потребителя, и поглощать сыр, вызывая метод Consumer::accept:

public static void main(String[] args) {

    List<Consumer<Cheese>> family = Arrays.asList(Mom::nip, Dad::gobble, Kid::bite);

    Cheese cheese = new Cheese();

    while (cheese.getWeight() > 0) {
        family.get(
            ThreadLocalRandom.current().nextInt(family.size())
        )
        .accept(cheese);
    }

    System.out.println("No cheese left");
}

→ Ссылка