MVC був охоплений у багатьох місцях, тому тут не повинно бути багато повторних. По суті, ви хочете, щоб ваш об'єктний графік, помічники та логіка містилися в ярусі моделі. Погляди будуть екранами, які висуваються для заповнення динамічної частини сторінки (і можуть містити невелику кількість логіки та помічників). І контролер, який є легкою реалізацією для обслуговування екранів на основі того, що було доступно з об'єктних графіків, помічників та логіки.
Модель
Це має бути там, де сидить м’ясо аплікації. Її можна розподілити на сервісний рівень, логічний рівень та сутність. Що це означає для вашого прикладу?
Субстанційний шар
Це має містити визначення моделей вашої гри та внутрішньої поведінки. Наприклад, якби у вас була гра для тральщика, саме тут описувались дошка та площа та визначення того, як вони змінюють свій внутрішній стан.
function Location(x,y){
this.x = x;
this.y = y;
}
function MineTile(x,y){
this.flagged = false;
this.hasMine = false;
this.pristine = true;
this.location = new Location(x,y);
}
MineTile.prototype.expose = function(){
if( this.hasMine ) return false;
this.pristine = false;
return this.location;
};
Таким чином, MineTile дізнається свій внутрішній стан, наприклад, якщо він показує або був досліджений ( this.pristine
), якщо це була одна з плиток, яка має шахту ( this.hasMine
), але не визначатиме, чи мала вона мати шахту. Це залежить від логічного шару. (Щоб піти ще далі в ООП, MineTile міг успадкувати від загальної плитки).
Логічний шар
Це має містити складні способи взаємодії програми із змінами режимів, збереженням стану тощо. Отже, саме тут буде реалізована модель посередника, щоб підтримувати стан поточної гри. Тут буде грати логіка гри для визначення того, що відбувається, наприклад, під час гри, або для встановлення того, який MineTiles матиме шахту. Здійснюватиме виклики в рівень Entity, щоб отримати рівні екземпляри на основі логічно визначених параметрів.
var MineSweeperLogic = {
construct: function(x,y,difficulty){
var mineSet = [];
var bombs = 7;
if( difficulty === "expert" ) bombs = 15;
for( var i = 0; i < x; i++ ){
for( var j = 0; i j < y; j++ ){
var mineTile = new MineTile(i,j);
mineTile.hasMine = bombs-- > 0;
mineSet.push(mineTile);
}
}
return mineSet;
},
mineAt: function(x,y,mineSet){
for( var i = 0; i < mineSet.length; i++ )
if( mineSet[i].x === x && mineSet[i].y === y ) return mineSet[i];
}
};
Сервісний рівень
Тут буде доступ до контролера. Він матиме доступ до логічного рівня для побудови ігор. Виклик високого рівня може здійснюватися в сервісний шар, щоб отримати повністю створену гру або модифікований стан гри.
function MineSweeper(x,y,difficulty){
this.x = x;
thix.y = y;
this.difficulty = difficulty;
this.mineSet = MineSweeperLogic.construct(x,y,difficulty);
}
MineSweeper.prototype.expose = function(x,y){
return MineSweeperLogic.mineAt(x,y,this.mineSet).expose();
}
Контролер
Контролери повинні мати невелику вагу, по суті, це те, що піддається клієнту моделі. Контролерів буде багато, тому їх структурування стане важливим. Виклики функції контролера - це те, що потрапляє в дзвінки javascript на основі подій інтерфейсу користувача. Вони повинні розкрити поведінку, доступну на рівні обслуговування, а потім заповнити або в цьому випадку змінити погляди для клієнта.
function MineSweeperController(ctx){
var this.context = ctx;
}
MineSweeperController.prototype.Start = function(x,y,difficulty){
this.game = new MineSweeper(x,y,difficulty);
this.view = new MineSweeperGameView(this.context,this.game.x,this.game.y,this.game.mineSet);
this.view.Update();
};
MineSweeperController.prototype.Select = function(x,y){
var result = this.game.expose(x,y);
if( result === false ) this.GameOver();
this.view.Select(result);
};
MineSweeperController.prototype.GameOver = function(){
this.view.Summary(this.game.FinalScore());
};
Вид
Погляди повинні бути організовані щодо поведінки контролера. Вони, мабуть, будуть найбільш інтенсивною частиною вашої заявки, оскільки вона стосується полотна.
function MineSweeperGameView(ctx,x,y,mineSet){
this.x = x;
this.y = y;
this.mineSet = mineSet;
this.context = ctx;
}
MineSweeperGameView.prototype.Update = function(){
//todo: heavy canvas modification
for(var mine in this.mineSet){}
this.context.fill();
}
Отже, у вас є ціла настройка MVC для цієї однієї гри. Або, принаймні, приклад голих кісток, написання всієї гри було б надмірним.
Після того, як це все буде зроблено, десь потрібно буде встановити глобальну область застосування. Це затримає термін експлуатації вашого поточного контролера, який є шлюзом до всього стеку MVC у цьому сценарії.
var currentGame;
var context = document.getElementById("masterCanvas").getContext('2d');
startMineSweeper.click = function(){
currentGame = new MineSweeperController(context);
currentGame.Start(25,25,"expert");
};
Використання шаблонів MVC дуже потужне, але не переживайте надто, щоб дотримуватися кожного їх нюансу. Зрештою, саме досвід гри визначить, чи буде програма успішною :)
Для розгляду: Не дозволяйте архітекторам архітектури лякати вас Джоелем Спольським