Как реализуется принцип открытости/закрытости в случае «ветвления» расширений в Java?
Есть сущность, которую нужно расширять. Исходя из всех способов расширения, которые указываются в OCP, основной — наследование. Если эту сущность расширяют только в одном направлении, то всё нормально. Но если эту сущность нужно расширять в разных направлениях, как быть? В Java нет множественного наследования.
Пример: Есть класс — Человек.
Через некоторое время, этот класс захотят расширить по OCP — унаследуются, и сделают класс Бармен.
Но если потом класс Человек захотят расширить и в другом направлении? Например — класс Космонавт, также унаследованный от класса Человек. При этом, если нужно, чтобы Человек являлся одновременно и Космонавтом, и Барменом, это не получится из-за того, что Бармен и Космонавт уже будут требовать отдельные экземпляры (instances), что соответствует двум разным людям.
Наследование типов а не классов. То есть через интерфейсы.
В Java нет множественного наследования.
В Java есть возможность делать композицию типов путем имплементации множества интерфейсов. А с учетом того что в Java8 у вас теперь есть возможность делать "дефолтные" имплементации методов в интерфейсах - у вас есть "правильное" наследование.
Через некоторое время, этот класс захотят расширить по OCP — унаследуются, и сделают класс Бармен.
А как потом быть если мы захотим сделать робота бармена? Я это к тому что "человек" не всегда будет являться базовым типом "бармена".
В целом Dmitry Roo вам верно сказал. "Бармен" это профессия. Свойство человека. У человека может быть много профессий:
class Human
{
Profession[] professions;
}
Таким образом мы можем крутить и вертеть как хотим.