数据结构~站点地图其实是一颗树
解放思想与面向对象两个东西有什么联系,怎么把它们放在一起去说了呢,呵呵,解放思想实事上是指将我们的习惯性思维进行改变,使用另一种方式来有效的解决一个问题,而这种解决问题的方法往往是通过面向对象的特性去实现的。
今天要说的是“站点地图也要面向对象“,我们通过在做站点地图时,都是直接写死在页面上的,这种方法的缺点就是修改起来比较麻烦,不易于扩展,如果要修改一个样式,那就要命了,你要一个页面一个页面的去改,呵呵。
我们应该把它进行抽象,来吧,请进入面向对象的世界里来,这里的世界是那么的美,他给开发人员带来的不仅是工作量少了,更重要的是使问题更加清晰了,代码艺术性更加强了,这对于一个枯燥的行业来说是至关重要的。
书归正传
首页 > 用户中心 > 我的订单
首页 > 用户中心 > 个人信息
上面的说明,很容易让我们想到的树型结构,没错,就是树型结构,有时,我们在开发程序时,运用合适数据结构可以帮助我们解决不少问题,思路清晰了,性能上去了,感觉把复杂的问题也简单化了,呵呵。
看看我的SiteMapTree
/// <summary> /// 站点地图 /// 树型结构 /// </summary> public class SiteMapTree { public SiteMapTree() { } public SiteMapTree(int id, string name, string linkUrl, bool isCurrent, int? parentID) { this.ID = id; this.Name = name; this.LinkUrl = linkUrl; this.IsCurrent = isCurrent; this.ParentID = parentID; } public int ID { get; set; } public string Name { get; set; } public string LinkUrl { get; set; } public bool IsCurrent { get; set; } public int? ParentID { get; set; } public List<SiteMapTree> Sons { get; set; } public SiteMapTree Father { get; set; } public static List<SiteMapTree> Data = new List<SiteMapTree>(); /// <summary> /// 初始化,填充基础数据 /// </summary> public static void Init() { Data.Add(new SiteMapTree(1, "网站首页", "#", false, null)); Data.Add(new SiteMapTree(2, "用户中心", "#", false, 1)); Data.Add(new SiteMapTree(3, "订单中心", "#", false, 2)); Data.Add(new SiteMapTree(4, "个人信息", "#", false, 2)); } }
而上面的类型我们通常称为实体类,而对于它的具体操作,可以通过一个功能类实现,事实上,对于这种树型结构来说,我们可以抽象出一个树型结构操作类,下
面我将一些常用的操作进行了实现。
/// <summary> /// 树的操作 /// </summary> public class Tree { List<SiteMapTree> Data; public Tree(List<SiteMapTree> data) { this.Data = data; } #region 树的装载 public SiteMapTree GetCompleteTree() { var root = Data.First(i => !i.ParentID.HasValue); GetSubTree(root); return root; } void GetSubTree(SiteMapTree tree) { List<SiteMapTree> sons = Data.Where(i => i.ParentID == tree.ID).ToList(); tree.Sons = sons; sons.ForEach(i => { i.Father = tree; GetSubTree(i); }); } #endregion #region 得到不完整的树 public SiteMapTree GetTree(int id) { var root = Data.First(i => i.ID == id); GetSubTree(root); return root; } #endregion #region 通过叶子节点得到它所有祖辈节点 public SiteMapTree GetAllFather(int id) { var root = Data.FirstOrDefault(i => i.ID == id); if (root != null) { GetFatherTree(root); } return root; } void GetFatherTree(SiteMapTree tree) { SiteMapTree father = Data.FirstOrDefault(i => i.ID == tree.ParentID); if (father != null) { tree.Father = father; GetFatherTree(father); } } #endregion }
上面的功能类,并不是很抽象,因为我没有去把它通用化,如,没有建立泛型机制,没有定义树型结构的统一接口等等,当然这在本例中不是重要的,接下来,我
们来看一下在具体环境中如何去使用这个站点地图:
/// <summary> /// 建立一个站点地图 /// </summary> /// <param name="?"></param> /// <param name="activeCss"></param> /// <returns></returns> public static MvcHtmlString CreateSiteMapTree( this HtmlHelper html, object id, string activeCss) { if (id == null) return null; int _id = Convert.ToInt32(id); SiteMapTree.Init(); Tree tree = new Tree(SiteMapTree.Data); if (tree == null) return null; var entity = tree.GetAllFather(_id); entity.IsCurrent = true; StringBuilder result = new StringBuilder(); FillFatherTree(result, entity, activeCss, true); result.Insert(0, "<div class='lx_indexcen_subnav'>"); result.Append("</div>"); return MvcHtmlString.Create(result.ToString()); } static void FillFatherTree(StringBuilder result, SiteMapTree tree, string activeCss, bool isHtml) { if (tree != null) { if (isHtml) { result.Insert(0, string.Format("<a href='{0}' title='{1}' class='{2}'>{1}</a>" , tree.LinkUrl , tree.Name , tree.IsCurrent ? activeCss : string.Empty)); } else { result.Append(tree.Name + "-"); } FillFatherTree(result, tree.Father, activeCss, isHtml); } }
在具体action中去调用它
ViewData["SiteMapID"] = SiteMapID;
事实上,上面的ViewData["SiteMapID"]一般是在母板页里进行展示的,呵呵。