ConstructiCat Logo
CodeBust.
Browse section ▾

Замена кодирования типа состоянием/стратегией.

Problem

У вас есть закодированный тип, который влияет на поведение, но вы не можете использовать подклассы, чтобы избавиться от него.

Solution

Замените кодирование типа объектом-состоянием. При необходимости заменить значение поля с кодированием типа, в него подставляется другой объект-состояние.

##Example

До
Replace Type Code with State-Strategy - Before
После
Replace Type Code with State-Strategy - After

##Why Refactor

У нас есть кодирование типа, и оно влияет на поведение класса, поэтому мы не можем заменить кодирования типа классом.

Кодирование типа влияет на поведение класса, но мы не можем создавать подклассы для закодированного типа ввиду наличия существующей иерархии классов или других причин. А значит, не можем применить замену кодирования типа подклассами.

##Benefits

  • Данный рефакторинг предоставляет выход из ситуации, когда поле с закодированным типом меняет своё значение в процессе жизни объекта. В этом случае, замена значения производится путём замены объекта-состояния, на который ссылается исходный класс.

  • Если вам потребуется добавить новое значение закодированного типа, все что придётся сделать — это добавить новый подкласс-состояние, не трогая существующий код (принцип открытости/закрытости).

##How to Refactor

  1. Используйте самоинкапсуляцию поля для создания геттера для поля, которое содержит кодирование типа.

  2. Создайте новый класс и дайте ему понятное название, соответствующее предназначению закодированного типа. Этот класс будет играть роль состояния (или стратегии). Создайте в нем абстрактный геттер закодированного поля.

  3. Создайте подклассы класса-состояния для каждого значения закодированного типа. В каждом подклассе переопределите геттер закодированного поля так, чтобы он возвращал соответствующее значение закодированного типа.

  4. В абстрактном классе состояния, создайте статический фабричный метод, принимающий в параметре значение закодированного типа. В зависимости от этого параметра, фабричный метод будет создавать объекты различных состояний. Для этого в его коде придётся создать большой условный оператор, но он будет единственным по завершению рефакторинга.

  5. В исходном классе, поменяйте тип закодированного поля на класс-состояние. В сеттере этого поля, вызывайте фабричный метод состояния для получения новых объектов состояний.

  6. Теперь можете начинать перемещать поля и методы из суперкласса в соответствующие подклассы-состояния (при помощи спуска поля и спуска метода).

  7. Когда все что можно перемещено, используйте замену условных операторов полиморфизмом, чтобы окончательно избавиться от условных операторов, использующий закодированный тип.