MVC đã được bao phủ ở rất nhiều nơi vì vậy không nên lặp lại nhiều ở đây. Về cơ bản, bạn muốn biểu đồ đối tượng, trình trợ giúp và logic của bạn được chứa trong lớp mô hình. Các khung nhìn sẽ là các màn hình được đẩy ra để lấp đầy phần động của trang (và có thể chứa một lượng logic và trợ giúp nhẹ). Và bộ điều khiển, là một triển khai nhẹ để phục vụ các màn hình dựa trên những gì có sẵn từ các biểu đồ đối tượng, trợ giúp và logic.
Mô hình
Đây phải là nơi thịt của ứng dụng ngồi. Nó có thể được xếp thành một lớp dịch vụ, lớp logic và lớp thực thể. Điều này có ý nghĩa gì với ví dụ của bạn?
Lớp thực thể
Điều này sẽ chứa các định nghĩa về mô hình và hành vi nội bộ của trò chơi của bạn. Ví dụ: nếu bạn có một trò chơi dành cho người quét mìn, đây sẽ là nơi định nghĩa bảng và hình vuông cùng với cách họ thay đổi trạng thái bên trong.
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;
};
Vì vậy, MineTile sẽ biết trạng thái bên trong của nó, chẳng hạn như nếu nó đang hiển thị hoặc đã được kiểm tra ( this.pristine
), nếu đó là một trong những ô có mỏ ( this.hasMine
) nhưng sẽ không xác định liệu nó có phải là của tôi không. Điều đó sẽ lên đến lớp logic. (Để đi xa hơn nữa vào OOP, MineTile có thể kế thừa từ một Ngói chung).
Lớp logic
Điều này sẽ áp dụng những cách phức tạp mà ứng dụng sẽ tương tác với việc thay đổi chế độ, giữ trạng thái, v.v. Vì vậy, đây sẽ là nơi mô hình hòa giải sẽ được thực hiện để duy trì trạng thái của trò chơi hiện tại. Đây sẽ là nơi logic trò chơi cư trú để xác định những gì xảy ra trong một trò chơi chẳng hạn, hoặc để thiết lập MineTiles nào sẽ có mỏ. Nó sẽ thực hiện các cuộc gọi vào lớp Thực thể để có được các mức khởi tạo dựa trên các tham số được xác định logic.
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];
}
};
Lớp dịch vụ
Đây sẽ là nơi bộ điều khiển có quyền truy cập. Nó sẽ có quyền truy cập vào lớp logic để xây dựng các trò chơi. Một cuộc gọi cấp cao có thể được thực hiện trong lớp dịch vụ để truy xuất một trò chơi được khởi tạo hoàn toàn hoặc trạng thái trò chơi được sửa đổ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();
}
Bộ điều khiển
Bộ điều khiển nên có trọng lượng nhẹ, về cơ bản đây là những gì được đưa ra với tư cách là khách hàng của mô hình. Sẽ có nhiều bộ điều khiển, vì vậy cấu trúc chúng sẽ trở nên quan trọng. Các lệnh gọi hàm điều khiển sẽ là những gì các lệnh gọi javascript dựa trên các sự kiện UI. Chúng nên phơi bày các hành vi có sẵn trong lớp dịch vụ và sau đó cư trú hoặc trong trường hợp này sửa đổi các khung nhìn cho máy khách.
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());
};
Lượt xem
Các khung nhìn nên được tổ chức liên quan đến hành vi của bộ điều khiển. Chúng có thể sẽ là phần chuyên sâu nhất trong ứng dụng của bạn vì nó liên quan đến canvas.
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();
}
Vì vậy, bây giờ bạn có toàn bộ thiết lập MVC cho một trò chơi này. Hoặc ít nhất, một ví dụ xương cốt, viết toàn bộ trò chơi sẽ là quá mức.
Một khi điều này được thực hiện, sẽ cần phải có một phạm vi toàn cầu cho ứng dụng ở đâu đó. Điều này sẽ giữ thời gian tồn tại của bộ điều khiển hiện tại của bạn, là cổng vào tất cả các ngăn xếp MVC trong kịch bản này.
var currentGame;
var context = document.getElementById("masterCanvas").getContext('2d');
startMineSweeper.click = function(){
currentGame = new MineSweeperController(context);
currentGame.Start(25,25,"expert");
};
Sử dụng các mẫu MVC rất mạnh mẽ, nhưng đừng quá lo lắng về việc tuân thủ mọi sắc thái của chúng. Cuối cùng, chính trải nghiệm trò chơi sẽ quyết định xem ứng dụng có thành công hay không :)
Để xem xét: Đừng để các phi hành gia kiến trúc sợ bạn bởi Joel Spolsky