Facade
Три Базовых класса мета-паттерна MVC представлены в PureMVC классами Модели, Представления и Контроллера. Чтобы упростить процесс разработки приложения, PureMVC задействует паттерн Фасад.
Фасад распределяет ваши запросы к Модели, Представлению и Контроллеру, так что ваш код не нуждается в импорте этих классов и вам не нужно работать с ними индивидуально. Класс Фасада автоматически создает экземпляры базовых синглтонов MVC в своем конструкторе.
Обычно Фасад самого фреймворка становится над-классом вашего приложения и используется для инициализации Контроллера с назначениями Команд. Подготовка Модели и Представления затем дирижируется Командами, выполняемыми Контроллером.
Что такое Конкретный Фасад (Concrete Facade)?
Хотя Базовые классы являются завершенными, готовыми к использованию реализациями, Фасад предоставляет реализацию, которую следует рассматривать как абстрактную в том смысле, что вы никогда не создаете его экземпляр непосредственным образом.
Вместо этого вы наследуете Фасад из фреймворка и / или переопределяете некоторые его методы, чтобы сделать их полезными конкретно для вашего приложения. (вы конкретизируете абстрактный Фасад фреймворка в конкретный Фасад своего приложения).
Этот конкретный Фасад затем используется для доступа и оповещения Команд, Медиаторов и Прокси, которые делают свою работу в системе. По соглашению, он называется ‘ApplicationFacade’, но вы можете назвать его как хотите.
В общем случае иерархия Представления вашего приложения будет создаваться согласно принятого для вашей платформы процесса. Как только построена иерархия Представления приложения, стартует аппарат PureMVC и регионы Модели и Вида готовятся к использованию.
Ваш конкретный Фасад также используется для облегчения процесса старта приложения, в том смысле, что он освобождает основной код приложения от необходимости глубокой осведомленности об аппарате PureMVC, к которому это приложение будет подключено. Приложение просто передает ссылку на себя в метод ‘startup’ синглтон-экземпляра вашего конкретного Фасада.
Создание Конкретного Фасада для вашего приложения
Вашему конкретному Фасаду не обязательно прилагать много усилий, чтобы передать приложению силу PureMVC. Рассмотрим следующую реализацию:
export default (Module) => {
const {
STARTUP,
Facade,
initialize, partOf, meta, property, method, nameBy
} = Module.NS;
@initialize
@partOf(Module)
class ApplicationFacade extends Facade {
@nameBy static __filename = __filename;
@meta static object = {};
@property _isInitialized: boolean = false;
@method startup(app) {
if (!this._isInitialized) {
this._isInitialized = true;
this.send(STARTUP, app);
}
}
@method initializeFacade(): void {
super.initializeFacade(... arguments)
this.rebind('ApplicationModule').toConstructor(this.Module);
this.addCommand(STARTUP, 'StartupCommand');
}
}
}
Отметим несколько моментов в приведенном выше коде:
- Он расширяет класс Facade PureMVC, который в свою очередь реализует интерфейс IFacade.
- Он не переопределяет конструктор. Если бы он это делал, то нужно было бы вызвать конструктор суперкласса прежде, чем делать чтолибо.
- Он определяет константы для имен Оповещений (STARTUP). Поскольку это игрок, используемый всеми другими участинками системы для доступа и связи друг с другом, конкретный Фасад является идеальным местом для определения констант, общих для всех участников обмена оповещениями.
- Он инициализирует Контроллер Командами, которые будут выполняться при отправке соответствующих Оповещений.
- Он предоставляет метод startup, который принимает один аргумент (в данном случае) типа MyApp, который с помощью Оповещения передается Команде StartupCommand (зарегистрированной на имя оповещения STARTUP).
С этими простыми требованиями реализации ваш конкретный Фасад унаследует ощутимую часть функциональности своего абстрактного класса-родителя.
Инициализация вашего Конкретного Фасада
Конструктор Фасада PureMVC вызывает защищенные методы для инициализации экземпляров Модели, Представления и Контроллера и кэширует их ссылки на них.
Затем по композиции Фасад реализует и делает доступными возможности Модели, Представления и Контроллера; агрегируя их функциональность и защищая разработчика от прямого взаимодействия с Базовыми классами фреймворка.
Итак, где и как Фасад внедряется в реальное положение вещей конкретного приложения? Рассмотрим упрощенный пример из реального приложения:
export default (Module) => {
const {
LIGHTWEIGHT,
initialize, partOf, meta, property, method, nameBy,
Utils: { uuid }
} = Module.NS;
@initialize
@partOf(Module)
class Application extends CoreObject {
@nameBy static __filename = __filename;
@meta static object = {};
@property isLightweight: boolean = false;
@property name: string = null;
@method start(): void {
this.facade.startup(this);
}
@method async finish(): Promise<void> {
await this.facade.remove();
}
constructor(name: string, ApplicationFacade: Class<*>, symbol: ?Symbol) {
const isLightweight = symbol === LIGHTWEIGHT;
if (isLightweight) {
const appName = `${name}|>${uuid.v4()}`
super(ApplicationFacade.getInstance(appName));
this.name = appName;
} else {
super(ApplicationFacade.getInstance(name));
this.name = name;
}
this.isLightweight = isLightweight;
}
}
}
Вот и все. Достаточно просто.
Создайте эту начальную иерархию вида, получите экземпляр ApplicationFacade и вызовите его метод startup.
Ключевые моменты этого примера:
- Поскольку мы инициализируем переменную вызовом статического метода ApplicationFacade.getInstance, то это означает, что в момент создания Application будет создан Фасад, а вместе с ним и Модель, Представление и Контроллер, хотя ни Медиаторы, ни Прокси не будут пока созданы.
- В отдельном методе start инстанса Application мы вызываем метод startup, передавая ему ссылку на главное приложение в качестве аргумента.
Заметьте, что обычные компоненты Представления не нуждаются в знании того, как им нужно взаимодействовать с Фасадом, но объект верхнего уровня Application является исключением для этого правила.
Верхнеуровневый объект Application строит иерархию Вида, инициализирует Фасад, а затем запускает аппарат PureMVC.