Пример с дополнением интерфейса:
class Playback {
private Media current;
public void play(Media media) {
current.stop();
current = media;
current.play();
}
public void next() {
Media media // получение следующей по какому либо алгоритму
play(media);
}
public void prev() {
Media media // получение предыдущей по какому либо алгоритму
play(media);
}
}
Пример с добавлением классов операций:
class Playback {
private Media current;
public Media current() {
return current;
}
public void play(Media media) {
current.stop();
current = media;
current.play();
}
}
abstract class PlayOperation {
private Playback playback;
public void execute() {
Media media = provide();
playback.play(media);
}
protected abstract Media provide();
}
class NextOperation extends PlayOperation {
public Media provide() {
Media media // получение следующей по какому либо алгоритму
return media;
}
}
class PrevOperation extends PlayOperation {
public Media provide() {
Media media // получение предыдущей по какому либо алгоритму
return media;
}
}
class RandomOperation extends PlayOperation {
private Random random;
public Media provide() {
Media media // получение рандомной
return media;
}
}
Пример с новыми классами выглядит привлекательнее, а стоит ли оно того?
Ответ
Пример с добавлением классов операций
То что вы описали в примере, это почти шаблон проектирования "Посетитель" . NextOperation , PrevOperation , RandomOperation - посетители класса Playback . В данном случае этот шаблон вряд ли обоснован, так как он призван добавлять поведение иерархии классов, и он действительно при работе с иерархией играет на OCP (т.к. необходимость добавления поведения в дерево наследников с помощью добавления метода в базовый класс как-раз нарушит OCP). У вас же класс один Playback - OCP не будет нарушено в первом случае - Playback открыт для расширения наследованием (если конечно поменять private на protected), и закрыт для изменения (это значит, что переписывать его вам не требуется для доработки поведения в наследниках).
Нельзя не увидеть минус второго подхода - вы серьёзно усложняете систему, размазывая простую логику на множество классов ( это Anti-SRP ). Поэтому я бы посоветовал оставить первый вариант, как минимум, когда система простая - так усложнять её нельзя, YAGNI против.
Но если Playback становится базовым классом иерархии - использование посетителей будет уже обосновано, и следует добавить метод visit(PlayOperation operation), при чём возможность посещения Playback - не значит что метод next(), например, обязательно должен быть вынесен в класс-посетитель: в посетителей лучше выносить дополнительные операции, а основные - оставлять внутри класса.
Комментариев нет:
Отправить комментарий