Это ключевое слово в лямбде - PullRequest
0 голосов
/ 02 января 2019

У меня есть 3 класса:

Событие

 public class Event<T> {
        private List<BiConsumer<Object, T>> consumers = new ArrayList<>();
        public void subscribe(BiConsumer<Object, T> consumer) {
            consumers.add(consumer);
        }
        public void invoke(Object sender, T arg) {
            for (BiConsumer<Object, T> consumer : consumers) {
                System.out.println(sender  + " " + "sender");
                consumer.accept(sender, arg);
            }
        }
    }

Крыса:

public class Rat  {
    private Game game;
    public Rat(Game game) {
        this.game = game;
        game.ratEnters.subscribe((sender, arg) -> {
            System.out.println( this + " " + sender);
        });
        System.out.println(this + "this");
        game.ratEnters.invoke(this, null);
    }
}

Игра:

public class Game {
    public Event ratEnters = new Event();
}

и одиночный тест:

public class ObserverPatternTest {

    @Test
    public void singleRatTest() {
        Game game = new Game();
        Rat rat  = new Rat(game);
        Rat rat2 = new Rat(game);
        Rat rat3 = new Rat(game);
    }

}

Выход:

design.patterns.behavioral.patterns.observer.exercises.Rat@4e515669this
design.patterns.behavioral.patterns.observer.exercises.Rat@4e515669 sender
design.patterns.behavioral.patterns.observer.exercises.Rat@4e515669 design.patterns.behavioral.patterns.observer.exercises.Rat@4e515669
design.patterns.behavioral.patterns.observer.exercises.Rat@17d10166this
design.patterns.behavioral.patterns.observer.exercises.Rat@17d10166 sender
design.patterns.behavioral.patterns.observer.exercises.Rat@4e515669 design.patterns.behavioral.patterns.observer.exercises.Rat@17d10166
design.patterns.behavioral.patterns.observer.exercises.Rat@17d10166 sender
design.patterns.behavioral.patterns.observer.exercises.Rat@17d10166 design.patterns.behavioral.patterns.observer.exercises.Rat@17d10166

Мой вопрос: каквозможно, что этот экземпляр не совпадает с экземпляром отправителя?

design.patterns.behavioral.patterns.observer.exercises.Rat@4e515669 design.patterns.behavioral.patterns.observer.exercises.Rat@17d10166

1 Ответ

0 голосов
/ 02 января 2019

Просто пытаюсь объяснить на примере полностью. Что произойдет с вашим кодом (, измененным для более читабельного вывода ) следующим образом:

Первый экземпляр

Rat rat1 = new Rat(game);

выполняется как:

this   ---->   pack.Sample$Rat@4cf777e8
sender     ---->   pack.Sample$Rat@4cf777e8
pack.Sample$Rat@4cf777e8  this   ---->  sender  pack.Sample$Rat@4cf777e8

Простой, верно? Я полагаю, что это было само собой разумеющимся, поскольку был создан единственный экземпляр ( 4cf777e8 ), просто список с одним потребителем, и все работает, как ожидалось.

Второй экземпляр

Затем при второй инициализации

Rat rat2 = new Rat(game);

вы теперь создали еще один экземпляр Rat ( 5702b3b1 ), который теперь становится sender в вашем Event.invoke вызове как:

// part-1
this   ---->   pack.Sample$Rat@5702b3b1
// part-2
sender     ---->   pack.Sample$Rat@5702b3b1
pack.Sample$Rat@4cf777e8  this   ---->  sender  pack.Sample$Rat@5702b3b1
sender     ---->   pack.Sample$Rat@5702b3b1
pack.Sample$Rat@5702b3b1  this   ---->  sender  pack.Sample$Rat@5702b3b1

вывод, который вы видите, разделен на две части, первая часть печатает текущий экземпляр этого и отправителя, который является последним созданным экземпляром.

Вторая часть имеет решающее значение, поскольку теперь она имеет List<BiConsumer<Object, T>>, в этом списке также есть предыдущий экземпляр Rat ( 4cf777e8 ), и это причина, по которой вы выполняете consumer.accept(sender, arg);, первый экземпляр появляется на рисунке: this указывает на его экземпляр и sender указывает на текущий sender, который вы передали в аргумент.

Третий экземпляр

Далее при последней инициализации

Rat rat3 = new Rat(game);

Теперь вы можете видеть, как вырос список consumers и его влияние на результат. Имейте в виду, что список теперь имеет BiConsumer с, каждый для созданного экземпляра Rat, т.е. Крыса (4cf777e8) , Крыса (5702b3b1) и Крыса @ 69ea3742 , как вы заметили бы на выходе.

// part-1
this   ---->   pack.Sample$Rat@69ea3742
// part-2
sender     ---->   pack.Sample$Rat@69ea3742
pack.Sample$Rat@4cf777e8  this   ---->  sender  pack.Sample$Rat@69ea3742 // (first element in list)
sender     ---->   pack.Sample$Rat@69ea3742
pack.Sample$Rat@5702b3b1  this   ---->  sender  pack.Sample$Rat@69ea3742 // (second element in list)
sender     ---->   pack.Sample$Rat@69ea3742
pack.Sample$Rat@69ea3742  this   ---->  sender  pack.Sample$Rat@69ea3742 // (third element in list)

упрощенный

Упрощенная версия вашего кода, чтобы проверить, что я придумал:

public static class Event {
    private List<Consumer<Object>> consumers = new ArrayList<>();

    void subscribe(Consumer<Object> consumer) {
        consumers.add(consumer);
    }

    void invoke(Object sender) {
        consumers.forEach(consumer -> {
            System.out.println("sender     ---->   " + sender);
            consumer.accept(sender);
        });
    }
}

public static class Rat {
    private Game game;

    Rat(Game game) {
        this.game = game;
        System.out.println("this   ---->   " + this);
        game.ratEnters.subscribe((sender) -> System.out.println(this + "  this   ---->  sender  " + sender));
        game.ratEnters.invoke(this);
    }
}

public static class Game {
    Event ratEnters = new Event();
}
...