ある企業のインタビューで、この質問をされました。
知っているデザインパターンは何ですか。それから、MVCデザインパターンに基づいた最も単純な「hello world」アプリケーションを書くように言われました。
JavaScriptプログラムを思いついた
var arr = ["a","b","c","d"]; // this is an array, same as store or model
alert(arr[0]); // this is controller
//and browser alert is a view.
後で私はアラートがビューであると言われました。私が知っているMVCの基本概念は、モデルの変更はすべてViewに報告されるということです。そして、その間にメソッドを呼び出すコントローラーがあります。
私のアプローチを修正したり、Hello World MVCアプリケーションの代替ソリューションを考え出してくれませんか。 MVCの微妙な側面についても説明します。
ありがとう。
var M = {}, V = {}, C = {};
M.data = "hello world";
V.render = function (M) { alert(M.data); }
C.handleOnload = function () { V.render(M); }
window.onload = C.handleOnLoad;
コントローラー(C
)は、何らかの相互作用/イベントストリームをリッスンします。この場合は、ページの読み込みイベントです。
モデル(M
)は、データソースを抽象化したものです。
ビュー(V
)は、モデルからデータをレンダリングする方法を知っています。
ControllerはViewに対して、Modelからの何かで何かをするように伝えます。
この例では
上記の例は、目的を示すために非常に単純化されていることに注意してください。 JS MVCワールドのreal "hello world"の例については、 todoMVC をご覧ください。
より良い例
var M = {}, V = {}, C = {};
/* Model View Controller Pattern with Form Example */
/* Controller Handles the Events */
M = {
data: {
userName : "Dummy Guy",
userNumber : "000000000"
},
setData : function(d){
this.data.userName = d.userName;
this.data.userNumber = d.userNumber;
},
getData : function(){
return data;
}
}
V = {
userName : document.querySelector("#inputUserName"),
userNumber : document.querySelector("#inputUserNumber"),
update: function(M){
this.userName.value = M.data.userName;
this.userNumber.value = M.data.userNumber;
}
}
C = {
model: M,
view: V,
handler: function(){
this.view.update(this.model);
}
}
document.querySelector(".submitBtn").addEventListener("click", function(){
C.handler.call(C);
});
/* Model Handles the Data */
/* View Handles the Display */
MVCアーキテクチャに関する記事を書きました。ここにあるのはほんの一部のコードだけです。
_//Modal
var modal = { data: "This is data"};
//View
var view = { display : function () {
console.log ("////////////////////////////");
console.log ( modal.data);
console.log ("////////////////////////////");
}
};
//Controller
var controller = ( function () {
view.display();
})();
_
上記の例から、この設計には3つの異なるユニットがあり、それぞれに実行する特定のジョブがあることがわかります。上記のインフラストラクチャからMVC設計を作成してみましょう。複数のビューとオブザーバーが存在する可能性があります。ここでは、最初に別のビューのみが作成されます。
_// Modal
var modal = { data: "This is data"};
// View
var slashView = { display : function () {
console.log ("////////////////////////////");
console.log ( modal.data);
console.log ("////////////////////////////");
}
};
var starView = { display : function () {
console.log ("****************************");
console.log ( modal.data);
console.log ("****************************");
}
};
// Controller
var controller = ( function () {
slashView.display();
starView.display();
})();
_
ここで理解されていることは、モーダルはビューまたはビューア、あるいはデータに対して実行された操作に依存してはならないということです。データモーダルは単独で使用できますが、ビューとコントローラーが必要です。1つはデータを表示し、もう1つはデータを操作する必要があるためです。したがって、モーダルのためにビューとコントローラーが作成され、その逆は作成されません。
_//Modal
var modal = {
data : ["JS in object based language"," JS implements prototypal inheritance"]
};
// View is created with modal
function View(m) {
this.modal = m;
this.display = function () {
console.log("***********************************");
console.log(this.modal.data[0]);
console.log("***********************************");
};
}
function Controller(v){
this.view = v;
this.informView = function(){
// update the modal
this.view.display();
};
}
// Test
var consoleView = new View(modal);
var controller = new Controller(consoleView);
controller.informView();
_
上記から、ビューとコントローラーの間にリンクが確立されていることがわかります。そして、これはMVCパターンの要件の1つです。モーダルの変更を示すために、プログラムを変更して、モーダルの状態の変更が独立して行われ、ビューに反映されていることを確認しましょう。
_//Modal
function Modal(){
this.state = 0;
this.data = ["JS is object based language","JS implements prototypal inheritance"];
//
this.getState = function (){
return this.state;
};
this.changeState = function (value) {
this.state = value;
};
}
// View is created with modal
function View(m) {
this.modal = m;
this.display = function () {
console.log("***********************************");
console.log(this.modal.data[modal.getState()]);
console.log("***********************************");
};
}
//controller is created with the view
function Controller(v){
this.view = v;
this.updateView = function(){
// update the view
this.view.display();
};
}
// Test
var modal = new Modal();
var consoleView = new View(modal);
var controller = new Controller(consoleView);
controller.updateView();
// change the state of the modal
modal.changeState(1);
controller.updateView();
_
モーダルの状態が変更されると、コントローラーはメッセージをビューに送信して自身を更新します。それは問題ありませんが、それでも1つの主要な概念を実装する必要があり、それはオブザーバーまたはコントローラーがモーダルによって識別される必要があるということです。これが発生することを確認するには、モーダルとコントローラーの間にリンクがあり、任意の数のコントローラーがモーダルへの関心を示すことができるようにする必要があります。これは、オブザーバーをモーダルに登録すると見なされます。このリレーションシップは、オブザーバーが空中に存在しないという概念を使用して実装されています。その存在は、モーダルに関心を持っているために発生します。したがって、モーダルは作成時に、モーダルを使用して作成する必要があります。つまり、モーダルにアクセスする必要があります。以下の例を見て、このMVC設計パターンがJavaScriptを使用して簡単かつエレガントに実現される方法を見てみましょう。
_function Modal(){
var stateChanged = false;
var state = 0;
var listeners = [];
var data = ["JS is object based language","JS implements prototypal inheritance"];
// To access the data
this.getData = function(){
return data;
};
// To get the current state
this.getState = function (){
return state;
};
// For simplicity sake we have added this helper function here to show
// what happens when the state of the data is changed
this.changeState = function (value) {
state = value;
stateChanged = true;
notifyAllObservers();
};
// All interested parties get notified of change
function notifyAllObservers (){
var i;
for(i = 0; i < listeners.length; i++){
listeners[i].notify();
}
};
// All interested parties are stored in an array of list
this.addObserver = function (listener){
listeners.Push(listener);
};
}
// View class, View is created with modal
function View(m) {
this.modal = m;
this.display = function () {
console.log("***********************************");
var data = this.modal.getData();
console.log(data[modal.getState()]);
console.log("***********************************");
};
}
// Controller or Observer class has access to both modal and a view
function Controller(m,v){
this.view = v;
this.modal = m;
this.modal.addObserver(this);
// update view
this.updateView = function(){
this.view.display();
};
// Receives notification from the modal
this.notify = function(){
// state has changed
this.updateView();
};
}
// Test
var modal = new Modal();
var consoleView = new View(modal);
var controller = new Controller(modal,consoleView);
// change the state of the modal
modal.changeState(1);
modal.changeState(0);
modal.changeState(1);
modal.changeState(0);
_
上記から、オブザーバーはモーダルaddObsever関数を使用して自身を登録し、モーダルへのリンクを確立していることがわかります。すべてのインスタンスが作成されたら。ビューに効果を表示するために、モーダル状態が手動で変更されました。通常、GUI環境では、ユーザーが任意のボタンを押すか、他の外部入力から変更が行われます。ランダムジェネレーターからの外部入力をシミュレートして、効果を観察できます。以下の例では、効果を明確に示すために、いくつかの要素がデータに追加されています。
_function Modal(){
var stateChanged = false;
var state = 0;
var listeners = [];
var data = [
"JS is object based language","JS implements prototypal inheritance",
"JS has many functional language features", "JS is loosely typed language",
"JS still dominates the Web", "JS is getting matured ","JS shares code
through prototypal inheritance","JS has many useful libraries like JQuery",
"JS is now known as ECMAScript","JS is said to rule the future of Web for
many years"];
//
this.getData = function(){
return data;
};
//
this.getState = function (){
return state;
};
this.changeState = function (value) {
state = value;
stateChanged = true;
notifyAllObservers();
};
function notifyAllObservers (){
var i;
for(i = 0; i < listeners.length; i++){
listeners[i].notify();
}
}
this.addObserver = function (listner){
listeners.Push(listner);
};
}
// View is created with modal
function View(m) {
this.modal = m;
this.display = function () {
console.log("****************************************************");
var data = this.modal.getData();
console.log(data[modal.getState()]);
};
//Adding external simulation of user sending input
this.pressButton = function(){
var seed = 10;
var number = Math.round(Math.random() * seed) ;
// change the state of modal
this.modal.changeState(number);
};
}
// Controller class needs modal and view to communicate
function Controller(m,v){
this.view = v;
//console.log(this.view.display);
this.modal = m;
this.modal.addObserver(this);
this.updateView = function(){
// update the view
//console.log(this.view);
this.view.display();
};
this.notify = function(){
// state has changed
this.updateView();
};
}
// Test
var modal = new Modal();
var consoleView = new View(modal);
var controller = new Controller(modal,consoleView);
// change the state of the modal
for ( var i = 0 ; i < 10; i++){
consoleView.pressButton();
}
_
上記の例は、モーダルがビューとコントローラーから独立しているMVCフレームワークの使用を示しています。データを表すモーダルは、関心を示し、モーダルに登録したすべての関係者に通知する責任があります。変更が発生するとすぐに、通知がパーティーに送信され、アクションはパーティーに残されます。以下の例は、新しく追加されたデータのみがオブザーバーによって表示される上記とは少し異なります。
_ function Modal(){
var stateChanged = false;
var listeners = [];
var data = ["JS is object based language"];
// To retrieve the data
this.getData = function(){
return data;
};
// To change the data by any action
this.modifyData = function (string) {
( data.length === 1 )? data.Push(string): data.unshift(string);
stateChanged = true;
notifyAllObservers();
};
// Notifies all observers
function notifyAllObservers (){
var i;
for(i = 0; i < listeners.length; i++){
listeners[i].notify();
}
}
// Requires to register all observers
this.addObserver = function (listener){
listeners.Push(listener);
};
}
// View is created with modal
function View(m) {
this.modal = m;
this.display = function () {
console.log("****************************************************");
var data = this.modal.getData();
console.log(data[0]);
console.log("****************************************************");
};
//Adding external simulation of user sending input
this.pressButton = function(string){
// change the state of modal
this.modal.modifyData(string);
};
}
// View class
function Controller(m,v){
this.view = v;
this.modal = m;
this.modal.addObserver(this);
// Updates the view
this.updateView = function(){
this.view.display();
};
// When notifies by the modal send the request of update
this.notify = function(){
// state has changed
this.updateView();
};
}
// Test
var modal = new Modal();
var consoleView = new View(modal);
var controller = new Controller(modal,consoleView);
consoleView.pressButton();
consoleView.pressButton("JS dominates the web world");
consoleView.pressButton("JQuery is a useful library of JS");
_
最後に追加したいのは、不要なときにオブザーバーを削除することです。これは、モーダル呼び出しにremoveObserver(object)
というメソッドを追加することで実行できます。上記のMVC設計パターンは、サブクラス化を使用し、トップクラスに共通の機能を持たせることで、より洗練されたものになり、設計ができるだけ単純になりますが、それは他の記事に残されています。それが役に立てば幸い。
MVCは、アプリケーションの構造化に使用する必要がある設計パターンです。 MVCはモデル、ビュー、コントロールの略です。基本的には、ビジネスロジック(モデル)をユーザーインターフェイス(ビュー)およびコントロールロジックから分離する必要があります。
例えば:
データベースからユーザーをロードするユーザークラスがあり、emを保存できます。これはあなたのモデルです。
Userクラスを使用してユーザーをログインさせるコントローラーがあります。
コントローラが完了すると、テキスト「Welcome $ username」を含むテンプレートが表示されます。
また、モデルはビューとコントローラーを認識してはならず、ビューはコントローラーを認識してはなりません。コントローラーはモデルとビューを認識します。
MVC上のWikipedia: http://de.wikipedia.org/wiki/Model_View_Controller
ここで要点を逃しているようです。
MVCは、アプリケーションの設計に使用するパターンです。少なくとも、モデルを変更して、ビューに反映された変更を確認できると思います。
通常、モデルを表すオブジェクト、「ビュー」(モデルとビューとして使用しているHTMLオブジェクトを仲介する可能性があります)を表す別のオブジェクト、および入力を受け取るコントローラーがあります。 HTMLオブジェクトから、モデルを更新します。
したがって、編集フィールドを変更すると、編集フィールドはコントローラーに通知し、コントローラーはモデルを更新します。モデルは、コントローラーがこのデータに依存する他のビューコンポーネントを更新するために使用するイベントを発生させます。
「hello world」バージョンを実装するのはあと数行ですが、これはこのようなインタビューの質問から探しているものだと思います。