而不会导致对这些对象的依赖性。各个视图实现Observer接口,并向模型注册。模型将跟踪由订阅更改的所有观察器组成的列表。当模型发生改变时,模型将会遍历所有已注册的观察器,并将更改通知它们。此方法通常称为“发布-订阅”。模型从不需要有关任何视图的特定信息。实际上,在需要将模型更改通知控制器的情况下(例如,启用或禁用菜单选项),控制器必须做的全部工作是实现Observer接口并订阅模型更改。对于存在许多视图的情况,定义多个主体是有意义的,其中每个主体都描述了特定类型的模型更改。然后,每个视图都只能订阅与视图有关的更改类型。图3显示了使用Observer的主动MVC的结构,以及观察器如何将模型与直接引用视图隔离开来。
图4说明当模型发生改变时Observer如何通知视图。可惜的是,在统一建模语言(UML)序列图中,没有好的方法来演示模型与视图的分离,因为该图表示的是对象的实例而不是类和接口。
MVC的ASP.NET实现
为了解释如何在ASP.NET中实现Model-View-Controller模式,并说明在软件中分离模型、视图和控制器角色的好处,下面的示例将一个没有分离所有三个角色的单页面解决方案重构为分离这三个角色的解决方案。示例应用程序是一个带有下拉列表的网页(如栏下图所示),该页面显示了存储在数据库中的记录。
利用Microsoft Visual Studio(r) .NET开发系统的代码隐藏功能,可以很容易地将表示(视图)代码与Model-Controller代码分离开来。每个ASP.NET页都有一种机制,这种机制允许在单独的类中实现从网页调用的方法。该机制是通过Visual Studio .NET提供的,它有许多优点,例如Microsoft IntelliSense(r)技术。当您使用代码隐藏功能来实现网页时,可以使用IntelliSense来显示网页后面的代码中所使用的对象的可用方法列表。IntelliSense不适用于.aspx页。与此同时,为了展现Model-Controller的分离,对于数据库操作提取了DatabaseGateway,这样就实现了三者的完整分离。
视图
<%@ Page language="c#" Codebehind="Solution.aspx.cs"
AutoEventWireup="false" Inherits="Solution" %>
<html>
<head>
<title>解决方案</title>
</head>
<body>
<form id="Solution" method="post" runat="server">
<h3>录音</h3>
选择录音:<br/>
<asp:dropdownlist id="recordingSelect" runat="server" />
<asp:button id="submit" runat="server" text="Submit"
enableviewstate="False" />
<p/>
<asp:datagrid id="MyDataGrid" runat="server" width="700"
backcolor="#ccccff" bordercolor="black" showfooter="false"
cellpadding="3" cellspacing="0" font-name="Verdana" font-size="8pt"
headerstyle-backcolor="#aaaadd" enableviewstate="false" />
</form>
</body>
</html>
模型
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);
图4说明当模型发生改变时Observer如何通知视图。可惜的是,在统一建模语言(UML)序列图中,没有好的方法来演示模型与视图的分离,因为该图表示的是对象的实例而不是类和接口。
MVC的ASP.NET实现
为了解释如何在ASP.NET中实现Model-View-Controller模式,并说明在软件中分离模型、视图和控制器角色的好处,下面的示例将一个没有分离所有三个角色的单页面解决方案重构为分离这三个角色的解决方案。示例应用程序是一个带有下拉列表的网页(如栏下图所示),该页面显示了存储在数据库中的记录。
利用Microsoft Visual Studio(r) .NET开发系统的代码隐藏功能,可以很容易地将表示(视图)代码与Model-Controller代码分离开来。每个ASP.NET页都有一种机制,这种机制允许在单独的类中实现从网页调用的方法。该机制是通过Visual Studio .NET提供的,它有许多优点,例如Microsoft IntelliSense(r)技术。当您使用代码隐藏功能来实现网页时,可以使用IntelliSense来显示网页后面的代码中所使用的对象的可用方法列表。IntelliSense不适用于.aspx页。与此同时,为了展现Model-Controller的分离,对于数据库操作提取了DatabaseGateway,这样就实现了三者的完整分离。
视图
<%@ Page language="c#" Codebehind="Solution.aspx.cs"
AutoEventWireup="false" Inherits="Solution" %>
<html>
<head>
<title>解决方案</title>
</head>
<body>
<form id="Solution" method="post" runat="server">
<h3>录音</h3>
选择录音:<br/>
<asp:dropdownlist id="recordingSelect" runat="server" />
<asp:button id="submit" runat="server" text="Submit"
enableviewstate="False" />
<p/>
<asp:datagrid id="MyDataGrid" runat="server" width="700"
backcolor="#ccccff" bordercolor="black" showfooter="false"
cellpadding="3" cellspacing="0" font-name="Verdana" font-size="8pt"
headerstyle-backcolor="#aaaadd" enableviewstate="false" />
</form>
</body>
</html>
模型
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);
| 对此文章发表了评论 |

