Замена подкласса полями
Проблема
У вас есть подклассы, которые отличаются только методами, возвращающими данные-константы.
Решение
Замените методы полями в родительском классе и удалите подклассы.
![Replace Subclass with Fields - Before](/images/refactoring/diagrams/Replace Subclass with Fields - Before.png?id=ea6525cc6b55e1a03fdb35def943c675)
![Replace Subclass with Fields - After](/images/refactoring/diagrams/Replace Subclass with Fields - After.png?id=bd1b29687aa333b3adbeb2bfb3e78614)
Причины рефакторинга
Бывает так, что вам нужно развернуть действие рефакторинга избавления от кодирования типа.
В одном из подобных случаев иерархия подклассов может отличаться только значениями, возвращаемыми определёнными методами. Причём эти значения не являются результатом вычисления, а жёстко прописаны либо в самих методах, либо в полях, возвращаемых методами. Чтобы упростить архитектуру классов, такая иерархия может быть свёрнута в один класс, содержащий одно или несколько полей с нужными значениями в зависимости от ситуации.
Нужда в этих изменениях могла возникнуть после перемещения большого числа функциональностей из иерархии классов куда-то в другое место. После этого текущая иерархия потеряла свою ценность, и подклассы стали создавать только избыточную сложность.
Достоинства
- Упрощает архитектуру системы. Создание подклассов — слишком избыточное решение, если все, что нужно сделать, это возвращать разные значения в нескольких методах.
Порядок рефакторинга
-
Примените к подклассам замену конструктора фабричным методом.
-
Замените вызовы конструкторов подклассов вызовами фабричного метода суперкласса.
-
Объявите в суперклассе поля для хранения значений каждого из методов подклассов, возвращающих константные значения.
-
Создайте защищённый конструктор суперкласса для инициализации новых полей.
-
Создайте или модифицируйте имеющиеся конструкторы подклассов, чтобы они вызывали новый конструктор родительского класса и передавали в него соответствующие значения.
-
Реализуйте каждый константный метод в родительском классе так, чтобы он возвращал значение соответствующего поля, а затем удалите метод из подкласса.
-
Если конструктор подкласса имеет какую-то дополнительную функциональность, примените встраивание метода для встраивания его конструктора в фабричный метод суперкласса.
-
Удалите подкласс.