Эм... А зачем кнопке контроллер то

Код AS3:
public final class AppPageModel {
private var location : String;
public function getLocation() : String {
return location;
}
public function setLocation(location : String) : void {
if (this.location == location)
return;
this.location = location;
fireListeners();
}
}
public final class SetAppPageAction implements Action {
private var location : String;
private var model : AppPageModel;
public function SetAppPageAction(location : String, model : AppPageModel) {
this.location = location;
this.model = model;
}
public function isAvailable() : Boolean {
return location != model.getLocation();
}
public function invoke() : void {
model.setLocation(location);
}
public function addChangeListener(f : Function) : void {
model.addChangeListener(f);
}
}
public static function renderMenu(model : AppPageModel, locations : Array) : DisplayObject {
const res : Sprite = new Sprite();
for each (var loc : String in locations) {
const btn : DisplayObject = renderButtonFor(new SetAppPageAction(loc, model));
/// place button.
res.addChild(btn);
}
return res;
}
Реальная обработка событий (за исключением интересных моментов) пропущена.
Модель плавно превращается в другую модель. В реальности промежуточных слоев может быть несколько. Но везде модели плавно превращаются в другие модели. Ключевой момент - любые действия - часть какой-то модели. Всегда. Если нужно - преобразуются в Action. Ну а для перехода пишется другой класс, который подписывается на изменения AppPageModel и делает все, что ему нужно.
На самом деле аналог AppPageModel лежит в библиотеке. Листалка страниц (без спецэффектов) - тоже. А еще семейство различных методов для создания всех возможных (в том числе и неизвестных заранее) типов кнопок

.
P.S. Да, Single Responsibility в действии. Хранение текущего места в одном классе, переход - в другом, отображение действия - в третьем (правда не факт, что классе).