读书人

打包一个树形菜单一类设计

发布时间: 2012-09-05 15:19:34 作者: rapoo

封装一个树形菜单一——类设计

[我有废话要说]
???? PA的U。M界面的树也是我封装的,做这个功能的时候,我希望它可以像smart-gwt的treeGrid一样好用。

???? 不过我不会C#,也第一次写ASP控件,还想让他像treeGrid……在这个难度上,我想再加点,把我的树写的通用又好维护,于是我决定好好设计,加入设计模式的思想:)
[正文——封个控件来画树]

? 需求:

??? 领导说写个读取XML配置,让后封装成树,在界面上展示出来。

??? 我是个画蛇添足的程序员,我想分两步完成,希望这个题目能两天就写完。

第一步:

??? 从XML解析一棵树,放到tree中。并且考虑:如果XML格式变了、如果不从XML取数据库……要让我的代码尽量满足开闭原则。

第二步:

??? 做一个渲染树的控件,将这个树丢到控件中,树就画出来了,可以多列。

?

开始干活:

我的树的设计

?

打包一个树形菜单一——类设计

?

用户通过工厂类得到一个XML工厂。

XMLTreeReader工厂解析XML文件,把XML配置的指定解析自己的ITreeReader返回。(比如扁平或层级的表示树形的XML文件)

ITreeReader一拿到就可以开始干活了,ITreeReader解析xml的节点,把数据封装到树结构ITreeNode中。

这里需要注意的是:ITreeNode表示一个树的树根节点,有节点的属性,还有子节点。因此ITreeReader解析时候,需要创建子节点,也就是ITreeNode对象。而ITreeNode是接口,不能new出来,所以ITreeReader需要知道ITreeNode的实现类,于是我传入ITreeReader一个ITreeNode的实现类,反射来创建对象。

?

?

using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace com.Origin.Base.test.mywork.Tree{    public interface ITreeReaderFactory    {        ITreeReader createTreeReader();    }}
using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace com.Origin.Base.test.mywork.Tree{    public class XMLTreeRreaderFactory:ITreeReaderFactory    {        private string xmlPath {set;get; }        public XMLTreeRreaderFactory(string path)         {            xmlPath = path;        }        public ITreeReader createTreeReader()        {            //解析xmlPath路径下的xml文件,根据XML配置取得解析该XML对应的类,反射回去.            //这里把解析XML的一段省略了先,直接写死读到了xml配置的类:            string className = "com.Origin.Base.test.mywork.Tree.SimpleTreeReader";            Type type = Type.GetType(className);            Console.WriteLine("    解析XML的类:" + type);            ITreeReader reader = (ITreeReader)type.Assembly.CreateInstance(className);            return reader;        }    }}
?
using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace com.Origin.Base.test.mywork.Tree{    public interface ITreeReader    {        ITreeNode createTree();    }}
?
using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace com.Origin.Base.test.mywork.Tree{    public class SimpleTreeReader:ITreeReader    {        private static string DEFAULT_NODE_CLASS = "com.Origin.Base.test.mywork.Tree.MyTreeNode";        private string treeNodeClassName { set; get; }        public ITreeNode createTree()         {            ITreeNode treeNode = createNode();            //根据XML的结构,解析XML文件,封装到ITreeNode的对象中,返回            //这里不读取XML了,直接用假数据封装下。            treeNode.putAttribute("name"," 用户管理");            treeNode.putAttribute("url"," /userManage.html");            //创建子树            ITreeNode subNode = createNode();            subNode.putAttribute("name", "创建用户");            subNode.putAttribute("url", " /createUser.html");            treeNode.addSubNode(subNode);            return treeNode;        }        private ITreeNode createNode()        {            if (treeNodeClassName == null)             {                treeNodeClassName = DEFAULT_NODE_CLASS;            }            //再次用到反射            Type type = Type.GetType(treeNodeClassName);            ITreeNode treeNode = (ITreeNode)type.Assembly.CreateInstance(treeNodeClassName);            return treeNode;        }    }}

?

using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace com.Origin.Base.test.mywork.Tree{    public abstract class ITreeNode    {        protected IList<ITreeNode> subNodes { get; set; }        //设置当前节点的key-value对        public abstract void putAttribute(object key, object value);               //根据key得到对应的值        public abstract object getAttribute(object key);               //为当前节增加一个子节点,在它的节点的下一级节点的末尾增加        public abstract void addSubNode(ITreeNode node);        public abstract IList<ITreeNode> getSubNodes();    }}
?

?

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Collections;namespace com.Origin.Base.test.mywork.Tree{    public class MyTreeNode : ITreeNode    {        private Hashtable attributes = new Hashtable();        //设置当前节点的key-value对        public override void putAttribute(object key, object value)        {            attributes.Add(key,value);        }        //根据key得到对应的值        public override object getAttribute(object key)        {            if (attributes.Contains(key))            {                return attributes[key];            }            else             {                return null;            }        }        //为当前节增加一个子节点,在它的节点的下一级节点的末尾增加        public override void addSubNode(ITreeNode node)         {            if (subNodes == null)             {                subNodes = new List<ITreeNode>();            }            subNodes.Add(node);        }        public override IList<ITreeNode> getSubNodes()        {            return subNodes;        }    }}

?

?看看client调用:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using com.Origin.Base.test.mywork.Tree;namespace ConsoleApplication1{    class Program    {        private ITreeReaderFactory factory = new XMLTreeRreaderFactory(@"D:\\menu.xml");        public ITreeNode fetchTreeNode()        {            ITreeNode root = null;            ITreeReader reader =  factory.createTreeReader();            root  = reader.createTree();            return root;        }        static void Main(string[] args)        {            Console.WriteLine("start...");            Program p = new Program();            ITreeNode root = p.fetchTreeNode();            string tab ="";            printTree(root, tab);                      Console.ReadLine();        }        public static void printTree(ITreeNode node,string s)        {            s = "  " + s;            Console.WriteLine(s + "NAME = " + node.getAttribute("name") + "  url = " + node.getAttribute("url"));            IList<ITreeNode> subNodes = node.getSubNodes();            if (subNodes == null)             {                return;            }            for (int i = 0; i < subNodes.Count; i++)            {                 printTree(subNodes[i],s);            }                }    }}
?

?输出:

打包一个树形菜单一——类设计

读书人网 >Web前端

热点推荐