Я пытаюсь реализовать шаблон стратегии в своем коде, но я столкнулся с чем-то, что не рассмотрено в примерах, которые я видел. И именно тогда стратегия должна ссылаться на метод, содержащийся в родительском классе.
Для простого примера (без родительского ссылки), давайте использовать пример Duck
и QuackBehaviour
:
class RubberDuck extends Duck {
public RubberDuck() {
setQuackBehaviour(new Squeak());
}
}
class Squeak implements QuackBehaviour {
public String quack() {
return "QUACK!";
}
}
Но что, если у нас теперь есть утка, которая любит называть свое имя? Это означало бы, что QuackBehaviour нужна какая-то ссылка на саму утку.
class PsyDuck extends Duck {
public PsyDuck() {
setQuackBehaviour(new SayName(this));
}
}
class SayName implements QuackBehaviour {
private Duck duck;
public SayName(Duck duck) {
this.duck = duck;
}
public String quack() {
return duck.getName();
}
}
Этот пахнет как плохой код для меня. Это анти-паттерн? Это предотвращает повторное использование QuackBehaviour объектом, не являющимся утиным. И что-то в отношении взаимозависимости между классами не устраивает меня.
Я думаю, вы могли бы также передать функцию в PsyDuck
, например:
class PsyDuck extends Duck {
public PsyDuck() {
setQuackBehaviour(new SayName(() => this.getName()));
}
}
Но если мы начинаем требовать множественные поля из поведения, тогда мы должны были бы передать много аргументов функции.
Или лучше SayName
быть абстрактным классом и PsyDuck
реализовать конкретную версию?
class PsyDuck extends Duck {
public PsyDuck() {
setQuackBehaviour(new PsyDuckSayName());
}
class PsyDuckSayName extends SayName {
protected String getName() {
return PsyDuck.this.getName();
}
}
}
abstract class SayName implements QuackBehaviour {
public String quack() {
return getName();
}
protected abstract String getName();
}
Последний подход кажется самым чистым, но я хотел бы получить некоторые отзывы и советы.