您的位置:首页 > 编程语言 > ASP

ASPNET MVC框架中的设计模式之模板方法模式

2016-05-23 21:00 585 查看

ASPNET MVC框架中的设计模式之模板方法模式

本文主要描述模板方法模式在ASPNET MVC框架中的应用。


模板方法模式是23种设计模式中相对简单的一种行为模式,类图不复杂。此模式中只涉及两种角色的类,分别是抽象类与具体实现类。模板 ASPNET MVC中对模板方法模式的最典型应用是其提供的注册区域功能,注册区域提供一种接口,能使开发人员简单快速地将Controller定义在其他Library项目中,实现模块化开发。

1. 模板方式模式

模板方法模式:在操作中定义一个算法的框架,并将其实现延迟到子类中。模板方法模式可以使其子类在不改变其父类定义的算法结构同时重新定义该算法的某些特定步骤。(Template Method Pattern: Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.)

模板方式模式的类图如下:



2.注册区域

一个大型Web项目通常会包含若干个项目,如果需要在两个以上的项目中同时包含Controller文件或者View文件;或者即使在同一个项目下,如果需要将Controller文件或者View文件放置在Controllers文件夹和Views文件夹以外的地方。都要通知MVC框架,Controller文件或者View文件不仅仅存在于启动项目的Controllers文件夹和Views文件夹下,还存在于本项目的其他文件夹或者其他项目的其他文件夹下。

ASPNET MVC框架提供的AreaRegistration类便用于解决此问题,在AreaRegistration的派生类中定义Controller文件和View文件出现的位置,然后在Application_Start方法中调用静态方法RegisterAllAreas注册所有的派生类。相当于在系统启动时通知MVC框架,在其他位置还存在Controller文件与View文件。

与Controller类所在文件夹的名称约定为Controllers类似,在Controllers和Views文件夹之外放置Controller文件和View文件的文件夹约定名称为Areas,一般称之为区域。Areas目录下可以有包含多个区域,例如Area1与Area2和Area3。其中每个区域必须对应一个AreaRegistration的派生类,此派生类的位置没有特殊要求。在每个派生的类中,用属性AreaName区分不同的区域。

那AreaRegistration类与其派生的子类是如何相互调用,从而达到通知MVC框架的效果呢?下面用代码分析来揭示这个过程。

AreaRegistration类的结构如下:

using System;
using System.Web.Routing;
namespace System.Web.Mvc
{
public abstract class AreaRegistration
{
public abstract string AreaName { get; }//需要在派生类中重写,用于区分不同的Area
public abstract void RegisterArea(AreaRegistrationContext context);//需要在派生类中重写,主要用于向全局路由表添加区域相关信息
internal void CreateContextAndRegister(RouteCollection routes, object state)
{
AreaRegistrationContext context = new AreaRegistrationContext(AreaName, routes, state);
........
RegisterArea(context);
}
public static void RegisterAllAreas()//一般在Application_Start中调用此方法
{
RegisterAllAreas(null);
}
public static void RegisterAllAreas(object state)
{
RegisterAllAreas(RouteTable.Routes, new BuildManagerWrapper(), state);//此处可知,后面routes参数即是全局路由信息的集合
}

internal static void RegisterAllAreas(RouteCollection routes, IBuildManager buildManager, object state)
{
List<Type> areaRegistrationTypes = TypeCacheUtil.GetFilteredTypesFromAssemblies(TypeCacheName, IsAreaRegistrationType, buildManager);
foreach (Type areaRegistrationType in areaRegistrationTypes)
{
AreaRegistration registration = (AreaRegistration)Activator.CreateInstance(areaRegistrationType);
registration.CreateContextAndRegister(routes, state);
}
}
}
}


在AreaRegistration类中,定义了一个抽象属性和一个抽象方法。其中抽象属性AreaName 在派生类中实现时,用于区分不同的区域,也就是不同的区域会返回不同的AreaName 。抽象方法RegisterArea则主要用于派生的子类向全局路由信息中加入与自身区域相关的信息。在派生类重写抽象方法RegisterArea时,涉及到一个重要的辅助类AreaRegistrationContext(其构造方法如下),此类在初始化时会传入RouteCollection 类型变量routes作为参数。从RegisterAllAreas的各个不同签名方法中可以发现,此处传入的routes即是RouteTable.Routes,里面存储着全局路由信息。

public class AreaRegistrationContext
{
public AreaRegistrationContext(string areaName, RouteCollection routes, object state);
public Route MapRoute(string name, string url, object defaults, object constraints, string[] namespaces)
{
......
Route route = Routes.MapRoute(name, url, defaults, constraints, namespaces);
......
}
}


在派生类重写RegisterArea方法时,会将此区域对应的路由信息通过AreaRegistrationContext类型参数context中的MapRoute方法加入到Routes属性中,也就是加入到全局的RouteTable里,从而达到向全局路由信息中加入与自身区域相关信息的效果。

public class AccountAreaRegistration:AreaRegistration//自定义类,派生于AreaRegistration
{
public override string AreaName
{
get { return "Account"; }
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Account_default",
"Account/{controller}/{action}/{id}",
new { controller = "Default", action = "Index", id = UrlParameter.Optional }
);

}
}


以下为区域注册中涉及到类之间关系。其中CMRAreaRegistration与AccountAreaRegistration是自定义类,派生于AreaRegistration。



对比模板方法模式的类图可以看出,在派生类中重写的抽象方法RegisterArea,是模板方法模式中的“基本方法”;而抽象类AreaRegistration中的RegisterAllAreas方法则是模板方法模式中的“模板方法”。“模板方法”中定义的“算法”则体现在父类获取到所有子类之后,分别从子类中调用CreateContextAndRegister方法的过程中。整个过程概括起来,就是在AreaRegistration类中用RegisterAllAreas和CreateContextAndRegister方法定义区域注册的全部过程,此过程中包括对了对抽象方法RegisterArea的引用。而抽象方法RegisterArea则在派生类中实现,其在实现过程中会加入各自区域的路由信息,达到区域注册到MVC框架的目的。如果需要增加其他区域,只需要增加一个派生类。在派生类实现抽象方法RegisterArea时,加入新增的区域路由信息。重新启动应用时,RegisterAllAreas方法会自动实例化所有派生类并将路由信息加入到全局路由表中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: