在 Web 项目中使用设计模式来解耦 UI 和业务逻辑实现






2.29/5 (6投票s)
2006 年 5 月 1 日
5分钟阅读

37205

264
一篇描述在中/大型 Web 项目中使用设计模式的文章
引言
正如标题所示,本文将介绍在中/大型 Web 项目中可能使用的设计模式,以解耦用户界面层和业务/应用程序层之间的通信。
设计模式:在软件工程的术语中,设计模式是软件设计中常见问题的标准解决方案。设计模式通常描述类、对象和通信流之间的交互的抽象系统。因此,描述一组交互类,这些类为特定上下文中的通用/特定设计问题提供通用的解决方案框架,可以被视为一种设计模式。换句话说,模式指的是针对特定软件设计问题的一种经过时间检验的解决方案(涉及一组交互类)。假定读者对基本设计模式有所了解,并熟悉 C# 和 .NET 环境。在本示例程序中将使用的两个主要模式是外观模式(Facade Pattern)和策略模式(Strategy Pattern)。
背景
外观模式:外观是一种面向对象的(object oriented)设计模式;本质上,它是一个为更大量的代码提供简化/统一接口的对象。在设计优秀程序时,优秀的设计师倾向于避免模块之间过度的耦合,而外观模式是实现这一目标的流行结构模式(structural pattern)。经典的“外观模式”使用的一个非常好的例子可以在此处找到。
策略模式:策略也是一种面向对象的、结构性的设计模式,主要关注将对象与其行为解耦,以便单个对象可以根据运行时场景执行几种不同的行为。许多设计师试图通过简单的子类化(subclassing)来实现策略模式(子类化一个对象以实现不同的功能)。然而,这是“静态”的策略实现,因为您必须创建一个不同的对象才能替换原始对象的行为。通过实际实现的策略模式,更改对象的策略将使其表现不同,并且无需提供任何条件语句来实现这一点。您可以在此处查看此示例。
本文中的代码将解释上述模式在基于 .NET 的 Web 项目中的使用,以将用户界面层(由专门的 UI 开发人员开发)与业务逻辑层(由另一组擅长实现业务逻辑的开发人员开发)解耦。假设我们的程序有两种不同的业务逻辑实现,并且要调用的实现取决于从 UI 提供的输入。独立的业务逻辑实现使用策略模式进行建模。UI 程序无需知道实际应该调用哪个业务实现。通过外观类对象,这种实现对用户界面是隐藏的。用户界面的职责仅限于将输入发送给外观对象。外观对象反过来根据截获的用户输入初始化策略对象。
代码解读
附加的代码包含一个 ASP.NET Web 客户端和一组类库。Web 客户端接受一个字符值,该值触发一个特定的业务流程执行;如果输入是 X,则应执行在类库 IndependantEntity1
中实现的业务流程,否则应执行在 IndependantEntity2
中封装的业务流程。
这看似是一个简单的需求;然而,它“模拟”了一个中等到大型的企业级 Web 应用程序的需求,其中需要根据 Web 用户收到的输入触发不同的业务流程。在这里,我们有意识地努力将 Web 客户端与业务层类库完全解耦;Web 客户端不知道根据输入将执行哪个业务流程。Web 客户端的唯一职责是创建一个正确的输入消息,并将该消息发送给外观对象。外观对象会截获请求,解析请求,并充当 IndependantEntity1
和 IndependantEntity2
程序集(可能由不同的团队实现)中实现的业务层逻辑算法的客户端。因此,我们以一种将客户端与其任何特定业务逻辑或算法的实现细节解耦的方式对其进行了设计。
实现策略模式的接口称为 IStrategy
,它只包含一个名为 ProcessMessage
的方法。由于接口就像一个契约,实现该接口的类必须为该方法提供实现体。IA1
和 IA2
是两个类,它们实现了我们示例项目两个独立且不相关的业务流程功能。这两个类都实现了 IStrategy
接口的 ProcessMessage
方法。
/*Interface definition. Interface.cs*/
using System;
namespace InterfaceProj
{
public interface IStrategy
{
bool ProcessMessage(string strXML, out string strMsg);
}
}
//-------------------------------------------------------------
//-------------------------------------------------------------
/*Interface implementation. IA1.cs*/
using System;
using InterfaceProj;
namespace IndependantEntity1
{
public class IA1: IStrategy
{
public IA1()
{
//
// TODO: Add constructor logic here
//
}
public bool ProcessMessage(string strXML,out string strMsg)
{
//parse XMl and do independant activity 1
strMsg = "Inside IA1";
return true;
}
private void DoSomeOtherIndependantActivity()
{}
}
}
RequestFacade
类充当所有 Web 请求的截获器。该类负责初始化策略对象并调用 ProcessMessage
功能。该类是外观模式的实现。
using System;
using InterfaceProj;
using IndependantEntity1;
using IndependantEntity2;
namespace RequestFacadeIntercept
{
/// <SUMMARY>
/// Summary description for RequestFacade.
/// </SUMMARY>
public class RequestFacade
{
private IStrategy objStrategy;
public RequestFacade()
{
//
// TODO: Add constructor logic here
//
}
/// <SUMMARY>
/// Process the input XML
/// Depending on the parsing instantiate the strategy object
///</SUMMARY>
public string SendRequest(string strInputXML)
{
string strMsg;
processXML(strInputXML);
//call Process
objStrategy.ProcessMessage(@"Input string extracted from XML",
out strMsg);
return strMsg;
}
private void processXML(string strInputXML)
{
//parse the xml and take appropriate decisions
if (strInputXML.Equals("X"))
objStrategy = new IA1();
else
objStrategy = new IA2();
}
}
}
实现策略模式的接口称为 IStrategy
,它只包含一个名为 ProcessMessage
的方法。由于接口就像一个契约,实现该接口的类必须为该方法提供实现体。IA1
和 IA2
是两个类,它们实现了我们示例项目两个独立且不相关的业务流程功能。这两个类都实现了 IStrategy
接口的 ProcessMessage
方法。
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using RequestFacadeIntercept;
namespace SampleWebproject
{
.............
public class WebForm1 : System.Web.UI.Page
{
..........
................
private void Button1_Click(object sender, System.EventArgs e)
{
string strSendXML = string.Empty;
strSendXML = TextBox1.Text.ToUpper();
//populate the string with some valid input XML
//create the RequestFacade object
//and send the XML input string to the
//SendRequest method for appropriate action
RequestFacade reqfacade = new RequestFacade();
lblResponse.Text = reqfacade.SendRequest(strSendXML);
//the web ui developer need to just create the
//XML based on pre supplied (out of scope of this demo)
//and call SendRequest
}
}
}
关注点
在任何中等到大型项目中,设计模式的使用都非常普遍。本示例仅演示了策略模式和外观模式在 Web 项目中的使用。而且,通过使用设计模式可以如此轻松地将 Web 客户端与业务逻辑实现解耦这一事实,应该鼓励在项目的设计阶段更多地使用此类模式。这还将消除 UI 设计师和业务逻辑开发人员之间的任何依赖关系;专业人员可以专注于自己的工作,而无需担心如何与彼此的工件进行通信。UI 和业务逻辑之间这种松散耦合也允许在不通知 UI 的情况下修改业务逻辑,只要外观层截获的输入消息保持不变。任何未来更改唯一需要修改的代码是外观对象。因此,应用程序的维护和可伸缩性问题也通过使用此类模式得到解决。
这只是一个示例。还有其他方法可以实现相同的目标。所以请继续探索设计模式。