MVCとは
MVCとはGUIアプリケーションのロジックを
データ部と表示部、そしてユーザー操作部分に分割する方法です。
今回はMVCパターンを適用しない形でアプリケーションを開発したあと、
MVCパターンを適用する形へリファクタリングします。
GUIDEでGUIを作成する
MATLABではGUIDEを利用してGUIを作成することができます。
注意点としてGUIDEでGUIを作成した場合に自動生成されるMコードでは
コールバックの外に変数を定義することができません。
つまり変数としてデータの状態を保存してコールバック間でデータを共有することが出来ません。
そこでコールバックのみ手動で定義することにします。
まずはGUIDEコマンドでGUIDEを起動します。
GUIDE
GUIDEを起動したらブランクGUIからコンポーネントを設置します。
コンポーネントを設置した後にCallbackとCreateFcnの割り当てを削除してください。
デフォルトでは%automatic
とコールバックの自動生成が宣言されていますので
記述を空白にしてください。
自動生成されたMコードから別の関数あるいはクラスへコンポーネントへの参照である変数handleを渡してください。
渡した先のコンストラクタ内でコールバックを手動で定義します。
function varargout = Test(varargin)
% End initialization code - DO NOT EDIT
% --- Executes just before Test is made visible.
function Test_OpeningFcn(hObject, eventdata, handles, varargin)
% UIWAIT makes Test wait for user response (see UIRESUME)
% uiwait(handles.figure1);
% --- Outputs from this function are returned to the command line.
function varargout = Test_OutputFcn(hObject, eventdata, handles)
% varargout cell array for returning output args (see VARARGOUT);
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Get default command line output from handles structure
varargout{1} = handles.output;
controller = TestController(handles); % 外部のクラスにコンポーネントへの参照を渡す
classdef TestController < handle
methods
function obj = TestController(handles)
count = 0;
set(handles.pushbutton1,'Callback',@obj.pushButton); % 手動でコールバックを設定
end
function pushButton(obj,hObject,eventdata) % コールバックには引数として呼び出し元のコンポーネントへの参照とイベントデータが必要
count = count + 1;
set(handles.text1,'String',num2str(count));
end
end
end
プッシュボタンを押すとテキストが数値に変更され、ボタンを押すたびに数が増加します。
MVCパターンの適用
MVCパターンを適用することでGUIアプリケーションを
- Model: データ処理を担当するアルゴリズム
- View: 表示を担当するアルゴリズム
- Controller: ユーザーの入力受付を担当するアルゴリズム
に分割します。
処理の責任をきっちり分担することでコードの見通しをよくし、改変に強いアプリケーションを開発することができます。
この際、ModelとViewはObserverパターンを適用して常にデータの同期を行います。
function varargout = Test(varargin)
% End initialization code - DO NOT EDIT
% --- Executes just before Test is made visible.
function Test_OpeningFcn(hObject, eventdata, handles, varargin)
% UIWAIT makes Test wait for user response (see UIRESUME)
% uiwait(handles.figure1);
% --- Outputs from this function are returned to the command line.
function varargout = Test_OutputFcn(hObject, eventdata, handles)
% varargout cell array for returning output args (see VARARGOUT);
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Get default command line output from handles structure
varargout{1} = handles.output;
model = TestModel(); % Modelを宣言
view = TestView(handles); % Viewを宣言
controller = TestController(); % Controllerを宣言
model.addObserver(view); % ViewをModelの観測者として登録
controller.setModel(model); % ControllerにModelを管理してもらう
controller.giveCallback(handles); % Controller内でコールバックを定義
classdef TestModel < handle
properties (SetAccess='private',GetAccess='private')
value
observers
end
methods
function obj = TestModel
obj.value = 0;
end
function value = getValue(obj)
value = obj.value;
end
function addValue(obj)
obj.value = obj.value + 1; % データの更新
obj.notifyToObservers(); % データの更新を観測者に伝える
end
function addObserver(obj,observer)
obj.observers = [obj.observers {observer}]; % 観測者を登録
end
end
methods (Access='private')
function notifyToObservers(obj)
for i = 1 : length(obj.observers)
obj.observers{i}.update(obj) % 観測者に自身への参照を渡して表示の更新を依頼
end
end
end
end
classdef TestView < handle
properties (SetAccess='private',GetAccess='private')
handles
end
methods
function obj = TestView(handles)
obj.handles = handles;
end
function update(obj,model)
set(obj.handles.text1,'String',num2str( model.getValue() )); % Modelの更新通知を受け取り表示を更新
end
end
end
classdef TestController < handle
properties (SetAccess='private',GetAccess='private')
model
end
methods
function setModel(obj,model)
obj.model = model;
end
function giveCallback(obj,handles)
set(handles.pushbutton1,'Callback',@obj.pushButton);
end
function pushButton(obj,hObject,eventdata)
obj.model.addValue(); % Modelを更新
end
end
end
より実践的なMVCパターンでは
複数のModel,View,Controllerがお互いにメッセージングを行いアプリケーションを構成します。
Mathworks、GUIDEやめるってよ