模型-視圖-控制器分離的重構(gòu)
為了解決上面所遺留的問(wèn)題,你必須將模型與控制器角色分離。
視圖的實(shí)現(xiàn)代碼與前部分相同。
模型
下面的代碼例子使模型角色僅僅依賴于數(shù)據(jù)庫(kù),而不包含任何與視圖相依賴的代碼。
using system;
using system.collections;
using system.data;
using system.data.sqlclient;
public class databasegateway
{
public static dataset getrecordings()
{
string selectcmd = "select * from recording";
sqlconnection myconnection =
new sqlconnection(
"server=(local);database=recordings;trusted_connection=yes");
sqldataadapter mycommand = new sqldataadapter(selectcmd, myconnection);
dataset ds = new dataset();
mycommand.fill(ds, "recording");
return ds;
}
public static dataset gettracks(string recordingid)
{
string selectcmd =
string.format(
"select * from track where recordingid = {0} order by id",
recordingid);
sqlconnection myconnection =
new sqlconnection(
"server=(local);database=recordings;trusted_connection=yes");
sqldataadapter mycommand = new sqldataadapter(selectcmd, myconnection);
dataset ds = new dataset();
mycommand.fill(ds, "track");
return ds;
}
現(xiàn)在的代碼只依賴于數(shù)據(jù)庫(kù),這個(gè)類是一個(gè)優(yōu)秀的數(shù)據(jù)庫(kù)的通道,它持有訪問(wèn)表或視圖的所用的sql語(yǔ)句,其它的代碼調(diào)用一些方法來(lái)完成與數(shù)據(jù)庫(kù)的交互。
控制器
這種重構(gòu)方式利用代碼隱藏機(jī)制,在負(fù)責(zé)數(shù)據(jù)訪問(wèn)的模型部分相對(duì)獨(dú)立的情況下,由控制器負(fù)責(zé)事件與方法的控制工作。模型的任務(wù)很明確的,它僅返回一個(gè)dataset對(duì)象。這種實(shí)現(xiàn)方式就像視圖代碼一樣,不依賴于數(shù)據(jù)是如何從數(shù)據(jù)庫(kù)中返回的。
using system;
using system.data;
using system.collections;
using system.web.ui.webcontrols;
public class solution : system.web.ui.page
{
protected system.web.ui.webcontrols.button submit;
protected system.web.ui.webcontrols.datagrid mydatagrid;
protected system.web.ui.webcontrols.dropdownlist recordingselect;
private void page_load(object sender, system.eventargs e)
{
if(!ispostback)
{
dataset ds = databasegateway.getrecordings();
recordingselect.datasource = ds;
recordingselect.datatextfield = "title";
recordingselect.datavaluefield = "id";
recordingselect.databind();
}
}
void submitbtn_click(object sender, eventargs e)
{
dataset ds =
databasegateway.gettracks(
(string)recordingselect.selecteditem.value);
mydatagrid.datasource = ds;
mydatagrid.databind();
}
#region web form designer generated code
override protected void oninit(eventargs e)
{
//
// codegen: this call is required by the asp.net web form designer.
//
initializecomponent();
base.oninit(e);
}
/// <summary>
/// required method for designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void initializecomponent()
{
this.submit.click += new system.eventhandler(this.submitbtn_click);
this.load += new system.eventhandler(this.page_load);
}
#endregion
}
測(cè)試
將模型部分從asp.net環(huán)境中分離出來(lái)能夠使模型部分更容易的被測(cè)試。在asp.net環(huán)境中進(jìn)行測(cè)試的話,你必須同時(shí)測(cè)試很多方面,如html代碼是否正確,而讀取html代碼的工作是非常煩悶的。將模型部分分離出來(lái),使你能夠?qū)δP筒糠肿鰡为?dú)的單元測(cè)試。下面是nunit (http://nunit.org)對(duì)模型部分進(jìn)行單元測(cè)試的例子。
using system;
using nunit.framework;
using system.collections;
using system.data;
using system.data.sqlclient;
[testfixture]
public class gatewayfixture
{
[test]
public void tracks1234query()
{
dataset ds = databasegateway.gettracks("1234");
assertion.assertequals(10, ds.tables["track"].rows.count);
}
[test]
public void tracks2345query()
{
dataset ds = databasegateway.gettracks("2345");
assertion.assertequals(3, ds.tables["track"].rows.count);
}
[test]
public void recordings()
{
dataset ds = databasegateway.getrecordings();
assertion.assertequals(4, ds.tables["recording"].rows.count);
datatable recording = ds.tables["recording"];
assertion.assertequals(4, recording.rows.count);
datarow firstrow = recording.rows[0];
string title = (string)firstrow["title"];
assertion.assertequals("up", title.trim());
}
}
結(jié)論:
在asp.net中實(shí)現(xiàn)mvc模式有如下優(yōu)缺點(diǎn):
優(yōu)勢(shì):
能夠減少依賴。 程序員可以在一個(gè)asp.net頁(yè)面中實(shí)現(xiàn)所有的代碼。單頁(yè)的實(shí)現(xiàn)方式,對(duì)于一些小型的且生存周期不長(zhǎng)的程序是適用的。但如果想在不斷增加的頁(yè)面間共享代碼的話,將代碼的不同部分進(jìn)行分離是非常有效果的。
能夠減少代碼的復(fù)制。 databasegateway 類中的getrecordings 和 gettracks方法能夠直接被其它的頁(yè)面使用,減少了必須將方法的代碼拷貝到不同頁(yè)面的情況。
能夠把不同人員的責(zé)任分開。修改頁(yè)面的外觀與修改數(shù)據(jù)訪問(wèn)的代碼所用的技術(shù)是不同的,將模型與視圖分開能夠使負(fù)責(zé)不同工作的專家協(xié)同的工作。
使性能優(yōu)化的成為可能 按將系統(tǒng)不同的職責(zé)分成不同的類,使性能的優(yōu)化成為可能。前面的例子中,由于每次請(qǐng)求頁(yè)面的時(shí)都要從數(shù)據(jù)庫(kù)中讀取數(shù)據(jù)。因此可在某種情況下將數(shù)據(jù)緩存,從而提高整個(gè)程序的性能。如果不將代碼進(jìn)行分離的話是無(wú)法做到的這點(diǎn)的。
易測(cè)試性 將模型與視圖相分離使在asp.net環(huán)境外進(jìn)行單元測(cè)試成為可能。
缺點(diǎn):
增加了代碼的數(shù)量及復(fù)雜度。這個(gè)例子在早期單頁(yè)的實(shí)現(xiàn)方式的基礎(chǔ)上增加了新的文件和代碼,在無(wú)形中增加了維護(hù)的開銷。一旦修改系統(tǒng)的話,會(huì)修改所有三種角色的代碼。在一些情況下,一個(gè)文件中的修改比一些文件中修改要方便。所以在考慮是否使用mvc模式時(shí)。這種額外的開銷一定要被計(jì)算在內(nèi),對(duì)一些小的程序來(lái)說(shuō),這種開銷是不值得的。
新聞熱點(diǎn)
疑難解答
圖片精選