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
) 이지만 광산 이 있는지 여부를 결정하지 않는 등의 내부 상태를 알 수 있습니다. 그것은 논리 계층에 달려 있습니다. (OOP로 나아 가기 위해 MineTile은 일반 타일에서 상속 할 수 있습니다).
논리 계층
여기에는 응용 프로그램이 모드 변경, 상태 유지 등과 상호 작용하는 복잡한 방법이 포함되어야합니다. 따라서 현재 게임의 상태를 유지하기 위해 중재자 패턴이 구현됩니다. 예를 들어 게임 오버 동안 발생하는 상황을 결정하거나 어떤 MineTiles에 광산이 있는지 설정하기 위해 게임 로직이있는 곳입니다. 논리적으로 결정된 매개 변수를 기반으로 인스턴스화 된 레벨을 얻기 위해 엔티티 계층을 호출합니다.
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();
}
제어 장치
컨트롤러는 가벼워 야합니다. 기본적으로 클라이언트가 모델에 노출되는 것입니다. 많은 컨트롤러가있을 것이므로이를 구성하는 것이 중요해질 것입니다. 컨트롤러 함수 호출은 자바 스크립트 호출이 UI 이벤트를 기반으로하는 것입니다. 서비스 계층에서 사용 가능한 동작을 노출 한 다음 클라이언트의보기를 채우거나 수정해야합니다.
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 패턴을 사용하는 것은 매우 강력하지만 모든 뉘앙스를 고수하는 것에 대해 너무 걱정하지 마십시오. 결국, 응용 프로그램의 성공 여부를 결정하는 것은 게임 경험입니다 :)
고려 사항 : 건축 우주 비행사들이 Joel Spolsky에 의해 당신을 겁 내게하지 마십시오