Как шаблон состояния может помочь в нашем коде

Шаблоны проектирования в разработке программного обеспечения являются важным инструментом при проектировании и кодировании программного обеспечения.

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

Конечно, есть много решений одной и той же проблемы, вы можете найти свое собственное решение, создать спагетти-код или применить шаблон проектирования, который соответствует вашей проблеме. Проблема возникает, когда вам нужно поддерживать свой код, если у вас есть беспорядок в вашем коде, вы, вероятно, внесете новые ошибки при добавлении функции или исправлении ошибок. Хороший дизайн поможет вам снизить вероятность внесения новых ошибок и, кроме того, быстро внести изменения.

Один из шаблонов, который я использовал больше, — это шаблон состояния. Эти паттерны очень просты, это Поведенческий паттерн, который позволяет изменять поведение объекта в зависимости от состояния.

Давайте посмотрим на короткий пример:

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

public class Window{
  public void open(){...}
  public void close(){...}
  public void lock(){...}
  public void unLock(){...}
}

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

public void open(){
 if (this.isClosed()) && (!this.isLocked()){
  ..... //code for opening window
 }
 
 if (this.isClosed()){
  throw new WindowClosedException();
 } 
 
 if (this.isLocked()){
  throw new WindowLockedException();
 }
}
public void open(){
….
}
public void close(){
….
}
public void lock(){
….
}
public void unLock(){
….
}
}

Что ж, у нас есть свой метод открытия окна. В других методах нам также придется проверять, заблокировано ли и закрыто ли окно…

Мы закодировали наш класс и работает отлично, пока мы не получим новые требования, теперь окно может быть разбито… поэтому мы также должны проверить, не разбито ли окно во всех методах. Также наш клиент попросил нас добавить новую функцию: изменить цвет окна (только когда окно закрыто и работает)….и наш код начинает расти с помощью ifs и условной проверки….красивый спагетти необслуживаемый код…

Подход к решению этой проблемы заключается в применении шаблона состояния. У нас будет абстрактное состояние, которое будет иметь все методы и вести себя в соответствии с состоянием:

public class Window{
 protected BaseWindowState currentState;
 
 public void open(){
  currentState.open();
 }
public void changeState(BaseWindowState newState){
  this.currentState = newState;
 }
}
public class WindowClosedState extends BaseWindowState {
@Override
 public void open(Window window){
  ..... //code for opening the window
  window.changeState(new WindowOpenedState());
 }
}

Теперь наш класс Window имеет текущее состояние, в котором мы направляем все поведение в текущее состояние. Состояние будет знать, как работать в соответствии с каждым классом состояния, например, WindowLockedState:

public class Window{
 protected BaseWindowState currentState;
 
 public void open(){
  currentState.open();
 }
 
 public void unLock(String password){
  currentState.unLock(password);
 }
public void changeState(BaseWindowState newState){
  this.currentState = newState;
 }
}
public class WindowLockedState extends BaseWindowState {
@Override
 public void open(Window window){
  throw new WindowLockedException();
 }
 
 @Override
 public void unLock(Window window,String password){
  ......//check for password to unLock
  window.changeState(new WindowClosedState()); //our window now is unlocked
 }  
}

Теперь вместо беспорядка с If у нас есть весь наш код отдельно в каждом состоянии в соответствии с его поведением. Это также позволяет легко добавлять новое поведение, добавляя новые состояния, и вы фокусируетесь только на поведении каждого состояния.

Есть некоторые улучшения, которые можно внести в этот подход, например, создать все возможные состояния и поместить их в список в классе Window, а затем при изменении состояния вы запрашиваете следующее состояние в списке.

Этот шаблон очень помог мне в моделировании решений, требующих разного поведения в каждом состоянии, например, симуляция устройства, в котором каждое состояние представляет собой экран, и на этом экране каждая кнопка ведет себя по-разному.