我建议你先从设计开始,不管你使用什么语言。想象一下,您需要再添加一个具有不同菜单项集的用户类型(例如,“Guest”)。那需要做什么呢?添加一个“if”语句,基本上是复制粘贴。这一点都不好。现在想象一下当你有 10 种用户类型时会发生什么。你的 switch-case 语句将变成巨大的怪物,团队中的每个人(甚至你)都会害怕在那里添加新项目或更改现有项目。
好吧,那很伤心,让我们现在玩得开心:)
理想情况下,您的“客户端”代码(我想您将放入 Page_Load 方法中)将只有一行:
protected void Page_Load(object sender, EventArgs e){
BuildMenu();
}
在您的方法中只有一行并且“神奇地”整理所有内容是多么酷。
假设我们有某种策略来管理我们的用户类型的可用项目。基本界面非常简单:
public abstract class MenuItemsPolicy{
public abstract List<MenuItem> GetMenuItems();
protected virtual MenuItem CreateMenuItem(string text, string url){
//add parameter checks, etc.
MenuItem item = new MenuItem();
item.Text = text;
item.NavigateUrl = url;
return item;
}
}
目前,我们有两种用户类型,所以我们将有两种实现。请求者:
public class RequestorMenuItems : MenuItemsPolicy{
public override List<MenuItem> GetMenuItems(){
return new List<MenuItem>(){
CreateMenuItem("Request A New Course", "~/Courses/RequestNewCourse.aspx"),
CreateMenuItem("View My New Course Requests", "~/Courses/ViewMyCourseRquests.aspx")
};
}
}
还有一个管理员(注意“合并”在哪里)
public class AdministratorMenuItems : MenuItemsPolicy{
public override List<MenuItem> GetMenuItems(){
List<MenuItem> resultingMenuItems = (new RequestorMenuItems()).GetMenuItems();
resultingMenuItems.Add(CreateMenuItem("View Un-Approved Requests", "~/Administration/ViewUnAprroved.aspx"));
return resultingMenuItems;
}
}
如您所见,我们检索请求者的项目,然后在那里再添加一项。如果将来需要更改,您的客户端/调用代码将不了解实现细节,因为您依赖于抽象实体。这意味着您不需要更改客户端/调用代码,规则将被更改;或者如果将来需要更改特定用户类型的可用链接。
为了简化示例,我将枚举用于用户类型:
public enum UserAccessType{
Requestor = 0,
Administrator = 1
}
现在,让我们看一下实现。我在页面上放置了一个简单而标准的 asp.net 菜单控件:
<form id="form1" runat="server">
<asp:menu runat="server" Id="mainMenu"></asp:menu>
<div>
这是“代码隐藏”:
public partial class _Default : System.Web.UI.Page{
//We will initialize this variable a bit later
//for example from URL parameter ?userType=1 or something like that
private UserAccessType _currentUserAccess;
//Ideally, dictionary should be a member of a class
//I left a simple dictionary just to avoid over-complicaation
private readonly Dictionary<UserAccessType, MenuItemsPolicy> _userMenuItems = new Dictionary<UserAccessType, MenuItemsPolicy>();
protected override void OnInit(EventArgs e){
//Associating our user types with Menu Items
_userMenuItems.Add(UserAccessType.Administrator, new AdministratorMenuItems());
_userMenuItems.Add(UserAccessType.Requestor, new RequestorMenuItems());
//Init the Current User / Access Type. For example, you can read the value from Request["UserType"]
//Here I've just assigned a value
_currentUserAccess = UserAccessType.Administrator;
base.OnInit(e);
}
protected void Page_Load(object sender, EventArgs e){
BuildMenu();
}
private void BuildMenu(){
mainMenu.Items.Clear();
var menuItems = GetMenuItems();
foreach(var item in menuItems){
mainMenu.Items.Add(item);
}
}
private List<MenuItem> GetMenuItems(){
MenuItemsPolicy currentPolicy = _userMenuItems[_currentUserAccess];
return currentPolicy.GetMenuItems();
}
}
我希望,上面的例子回答了你的问题。当然,这个例子并不理想。但是,它有助于保持您的代码相对干净和可维护。
PS我确实建议你阅读这篇文章:
http: //objectmentor.com/resources/articles/Principles_and_Patterns.pdf
请参阅 OCP 示例 - 您会看到它与您的情况有多接近。
谢谢阅读 :)