Контролер аплікації (шаблон проєктування)

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до навігації Перейти до пошуку

Контролер аплікації (англ. Application Controller) — шаблон проєктування, який дозволяє керувати порядком роботи аплікації залежно від стану.

Опис[ред. | ред. код]

Контролери сторінки відповідають за представлення сторінки користувачеві. При збільшені складності логіки аплікації вибір представлення дублюється в різних контролерах. Якщо логіка вибору представлення проста (інакше кажучи, якщо користувач може відкривати сторінки у довільному порядку), контролери сторінок являються самодостатніми, та не потребують змін. У випадку коли порядок відображення сторінок має значення в залежності від стану об'єкту, варто змінювати логіку.

Щоб запобігти повторам, необхідно винести логіку керування потоком виконання аплікації в окремий клас. В такому випадку контролери сторінок запитують контролери аплікації за операції, які варто виконати над моделлю та за представлення, яке необхідно відобразити користувачу.

Реалізація[ред. | ред. код]

Змоделюємо доменну область електронних черг. Нехай необхідно забронювати час на прийом до лікаря. Тоді потік виконання програми можна описати наступними кроками

Бронювання часу

  1. При спробі забронювати час можливий перехід в один із наступних станів:
    1. Стан помилки. На даний момент немає доступний вільних місць, час забронювати не вдалось.
    2. Підтвердження бронювання. Вільні місця є, час забронювати можна, необхідне підтвердження.

Підтвердження бронювання

Стан при якому користувач отримує повідомлення із кодом підтвердження.

  1. При підтверджені бронювання можливий перехід в один із наступних станів:
    1. Стан помилки. Введений код не вірний.
    2. Час заброньовано. Введений код вірний, бронювання підтверджено та створено.

Опишемо операції над моделлю предметної області у вигляді команд.

interface IReadOnlyState
{
	object GetModel();
	string GetViewName();
}

interface IState : IReadOnlyState
{
	IState Execute();
}

class CreateReservationState : IState
{
	public IState Execute()
	{
	 	// перевірка наявності місць
		if (new Random().NextDouble() < 0.25)
		{
			return new ErrorState();
		}
		
		return new ConfirmReservationState();
	}
	
	public object GetModel() => new ReservationViewModel();
	public string GetViewName() => "CreateReservationPage";
}

class ConfirmReservationState : IState
{
	public IState Execute() 
	{	
		// перевірка коду
		if (new Random().NextDouble() < 0.25)
		{
			return new ErrorState();
		}
		
		return new ReservationCreatedState();
	}
	public object GetModel() => new ConfirmReservationViewModel();
	public string GetViewName() => "ConfirmPage";
}

class ReservationCreatedState : IState
{
	public IState Execute() => null;
	public object GetModel() => new ReservationCreatedViewModel();
	public string GetViewName() => "SuccessPage";
}

class ErrorState : IState
{
	public IState Execute() => null;
	public object GetModel() => new ErrorViewModel();
	public string GetViewName() => "ErrorPage";
}

Тоді контролери матимуть наступний вигляд:

class ApplicationController
{
	private readonly Stack<IState> _history = new Stack<IState>();	
	
	public ApplicationController()
	{
		_history.Push(new CreateReservationState());
	}
	
	public IReadOnlyState GetNextView()
	{
		// зміна стану
		var state = _history.Peek();
		
		var nextState = state.Execute();
		if (nextState != null) _history.Push(nextState);
		
		return state;
	}
	
	public string GoBack()
	{
		return _history.Pop().GetViewName();
	}
}

class ReservationController
{
	private readonly ApplicationController _applicationController = new ApplicationController();	
	
	public ViewResult PressButton()
	{
		var state = _applicationController.GetNextView();
		
		return View(state.GetViewName(), state.GetModel());
	}
}

Див. також[ред. | ред. код]

Джерела[ред. | ред. код]