Страницы

Поиск по вопросам

четверг, 23 января 2020 г.

Трактовка принципа Открытости-Закрытости

#java #ооп #solid


Пример с дополнением интерфейса:  

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;
    }
}


Пример с новыми классами выглядит привлекательнее, а стоит ли оно того?
    


Ответы

Ответ 1



Пример с добавлением классов операций То что вы описали в примере, это почти шаблон проектирования "Посетитель" . NextOperation , PrevOperation , RandomOperation - посетители класса Playback . В данном случае этот шаблон вряд ли обоснован, так как он призван добавлять поведение иерархии классов, и он действительно при работе с иерархией играет на OCP (т.к. необходимость добавления поведения в дерево наследников с помощью добавления метода в базовый класс как-раз нарушит OCP). У вас же класс один Playback - OCP не будет нарушено в первом случае - Playback открыт для расширения наследованием (если конечно поменять private на protected), и закрыт для изменения (это значит, что переписывать его вам не требуется для доработки поведения в наследниках). Нельзя не увидеть минус второго подхода - вы серьёзно усложняете систему, размазывая простую логику на множество классов ( это Anti-SRP ). Поэтому я бы посоветовал оставить первый вариант, как минимум, когда система простая - так усложнять её нельзя, YAGNI против. Но если Playback становится базовым классом иерархии - использование посетителей будет уже обосновано, и следует добавить метод visit(PlayOperation operation), при чём возможность посещения Playback - не значит что метод next(), например, обязательно должен быть вынесен в класс-посетитель: в посетителей лучше выносить дополнительные операции, а основные - оставлять внутри класса.

Комментариев нет:

Отправить комментарий