摘要: 我觉得泛型一个最核心的地方就是,泛型封装了类型,把类型的定义延迟到了客户端,泛型又像一个类型的模板,只要你定义了一个泛型类,就相当于定义了N个类,每个类的类型不一样而已 阅读全文
posted @ 2011-08-07 09:36 lawbc 阅读(8583) 评论(56) 推荐(41) 编辑

晚上无聊写了个二叉树(图)的广度和深度遍历算法,算法本身很简单,但是如何做到通用呢,一下代码是我的设计,请大家帮忙看看有什么问题,我自己感觉有问题就是不知道具体什么问题

    public interface IGraph<TVertex>
    {
        IEnumerable<IEdge<TVertex>> Edges { get; }
    }
    public interface IEdge<TVertex>
    {
        TVertex From { get; set; }
        TVertex To { get; set; }
    }
    public interface INode
    {
        IEnumerable<TNode> GetNextNodes<TNode>() where TNode : INode;
    }
    public class Edge<TVertex> : IEdge<TVertex>
    {
        public TVertex From { get; set; }
        public TVertex To { get; set; }
    }
    public static class NodeVisitor
    {
        public static void BreadthVisit<TNode>(TNode rootNode, Action<TNode> visitAction)
           where TNode : INode
        {
            BreadthVisit(rootNode, n => n.GetNextNodes<TNode>(), visitAction);
        }

        public static void BreadthVisit<TNode>(TNode rootNode, Func<TNode,IEnumerable<TNode>> nextNodeSelector, Action<TNode> visitAction)
        {
            var nodeQueue = new Queue<TNode>();
            nodeQueue.Enqueue(rootNode);
            while (nodeQueue.Any())
            {
                var currentNode = nodeQueue.Dequeue();
                if (visitAction != null)
                {
                    visitAction(currentNode);
                }
                foreach (var nextNode in nextNodeSelector(currentNode))
                {
                    nodeQueue.Enqueue(nextNode);
                }
            }
        }

        public static void DepthVisit<TNode>(TNode rootNode, Func<TNode, IEnumerable<TNode>> nextNodeSelector, Action<TNode> visitAction)
        {
            var nodeStack = new Stack<TNode>();
            nodeStack.Push(rootNode);
            while (nodeStack.Any())
            {
                var currentNode = nodeStack.Pop();
                if (visitAction != null)
                {
                    visitAction(currentNode);
                }
                foreach (var nextNode in nextNodeSeletor(currentNode))
                {
                    nodeStack.Push(nextNode);
                }
            }
        }

        public static void DepthVisit<TNode>(TNode rootNode, Action<TNode> visitAction)
           where TNode : INode
        {
            DepthVisit(rootNode, n => n.GetNextNodes<TNode>(), visitAction);
        }
    }
    public class GraphVisitor<TVertex> 
    {
        private IGraph<TVertex> _graph;

        public GraphVisitor(IGraph<TVertex> graph)
        {
            _graph = graph;
        }

        public TVertex GetRoot()
        {
            var vertexs = _graph.Edges.Select(t => t.From).Concat(_graph.Edges.Select(t => t.To));
            var toVertexs = _graph.Edges.Select(t => t.To);
            return vertexs.FirstOrDefault(t => toVertexs.All(v => !v.Equals(t)));
        }

        public IEnumerable<TVertex> GetNextVertexs(TVertex current)
        {
            return _graph.Edges.Where(t => t.From.Equals(current)).Select(t => t.To);
        }

        public void BreadthVisit(Action<TVertex> visitAction, TVertex startVertex)
        {
            NodeVisitor.BreadthVisit(startVertex, t => GetNextVertexs(t), visitAction);
        }

        public void BreadthVisit(Action<TVertex> visitAction)
        {
            NodeVisitor.BreadthVisit(GetRoot(), t => GetNextVertexs(t), visitAction);
        }

        public void DepthVisit(Action<TVertex> visitAction, TVertex startVertex)
        {
            NodeVisitor.DepthVisit(startVertex, t => GetNextVertexs(t), visitAction);
        }

        public void DepthVisit(Action<TVertex> visitAction)
        {
            NodeVisitor.DepthVisit(GetRoot(), t => GetNextVertexs(t), visitAction);
        }

        private class GraphNode : INode
        {
            private IList<INode> nodes = new List<INode>();

            public string Id { get; set; }

            public void AddNext(INode node)
            {
                nodes.Add(node);
            }

            public IEnumerable<TNode> GetNextNodes<TNode>() where TNode : INode
            {
                return nodes.Cast<TNode>();
            }
        }
    }

 单元测试代码:

    [TestClass]
    public class BreadthVisitorTest
    {
        [TestMethod]
        public void TestVisit()
        {
            var node1 = new TestNode() { Id = "1" };

            var node1_1 = new TestNode() { Id = "1_1" };
            var node1_2 = new TestNode() { Id = "1_2" };

            var node1_1_1 = new TestNode() { Id = "1_1_1" };
            var node1_1_2 = new TestNode() { Id = "1_1_2" };
            var node1_1_3 = new TestNode() { Id = "1_1_3" };

            var node1_2_1 = new TestNode() { Id = "1_2_1" };
            var node1_2_2 = new TestNode() { Id = "1_2_2" };

            node1.AddNext(node1_1);
            node1.AddNext(node1_2);

            node1_1.AddNext(node1_1_1);
            node1_1.AddNext(node1_1_2);
            node1_1.AddNext(node1_1_3);

            node1_2.AddNext(node1_2_1);
            node1_2.AddNext(node1_2_2);
            var expected = "1.1_1.1_2.1_1_1.1_1_2.1_1_3.1_2_1.1_2_2";
            var actual = "";
            NodeVisitor.BreadthVisit(node1, n => {
                actual += n.Id + ".";
            });

            Assert.AreEqual(expected, actual.Trim('.'));

            expected = "1.1_1.1_1_1.1_1_2.1_1_3.1_2.1_2_1.1_2_2";
            actual = "";
            NodeVisitor.DepthVisit(node1, n => {
                actual += n.Id + ".";
            });
        }

        [TestMethod]
        public void TestGraphVisit()
        {
            var graph = new Graph();
            var graphVisitor = new GraphVisitor<int>(graph);

            graph.AddEdge(1, 2);
            graph.AddEdge(1, 3);

            graph.AddEdge(2, 4);
            graph.AddEdge(2, 5);

            graph.AddEdge(3, 6);

            var expected = "123456";
            var actual = "";

            graphVisitor.BreadthVisit(a => { actual += a.ToString(); });

            Assert.AreEqual(expected, actual);

            expected = "124536";
            actual = "";
            graphVisitor.DepthVisit(a => { actual += a.ToString(); });

        }
    }

    public class TestNode : INode
    {
        private IList<INode> nodes = new List<INode>();

        public string Id { get; set; }

        public void AddNext(INode node)
        {
            nodes.Add(node);
        }

        public IEnumerable<TNode> GetNextNodes<TNode>() where TNode : INode
        {
            return nodes.Cast<TNode>();
        }
    }

    public class Graph : IGraph<int>
    {
        private IList<IEdge<int>> _edges = new List<IEdge<int>>();
        public IEnumerable<IEdge<int>> Edges
        {
            get
            {
                return _edges;
            }
        }

        public void AddEdge(int from, int to)
        {
            _edges.Add(new Edge<int>() { From = from, To = to });
        }
    }
View Code

 

posted @ 2016-06-23 01:05 lawbc 阅读(1159) 评论(0) 推荐(0) 编辑
摘要: DDD领域驱动设计走马观花之聚合、实体、值对象 阅读全文
posted @ 2014-08-27 08:34 lawbc 阅读(7242) 评论(4) 推荐(1) 编辑
摘要: 什么是运用层,说白了就是以前三层的BLL,没有什么特别,只是调用的不是以前的DAL了,而是领域层+基础设施层,运用层接口基本是可以根据原型来做的,也就是UI需要什么数据就定义什么接口,难点就在于怎么去调用领域层了,这个如果是分开来开发的话,难度会很大,为什么是很难呢,原因就在于区分职责,需要有很详细的领域层说明以及实时的参与领域建模。 阅读全文
posted @ 2014-08-26 21:49 lawbc 阅读(1799) 评论(0) 推荐(0) 编辑
摘要: 什么是领域服务,DDD书中是说,有些类或者方法,放实体A也不好,放实体B也不好,因为很可能会涉及多个实体或者聚合的交互(也可能是多个相同类型的实体),此时就应该吧这些代码放到领域服务中,领域服务其实就跟传统三层的BLL很相似,只有方法没有属性,也就没有状态,而且最好是用动词命名,service为后缀,但是真正到了实践的时候,很多时候是很难区分是领域实体本身实现还是用领域服务区实现的,除了那些需要操作(一般是参数了)多个实体的方法外,有些单个实体的操作是很难严格区分的,实际上放实体和领域服务都可以,只是会有技术上的实现问题,比如实体里面怎么注入仓促的问题,如果放领域服务中了,就很容易注入了;还有一点就是实体或者聚合最好是不要去调用领域服务的,真是没有必要,如果要也会存在注入问题,所以比较合适的实践是,一些方法,如果有涉及系统性判断,如用户名唯一这种查找表的,那么就放到领域服务中,让运用层来调用,领域服务在去调用仓储。 阅读全文
posted @ 2014-08-26 21:31 lawbc 阅读(6703) 评论(7) 推荐(4) 编辑
摘要: 其实这里说的基础设施层只是领域层的一些接口和基类而已,没有其他的如日子工具等代码,仅仅是为了说明领域层的一些基础问题 阅读全文
posted @ 2014-08-26 21:18 lawbc 阅读(5752) 评论(0) 推荐(2) 编辑
摘要: 讨论怎么根据需求提取领域模型,一步一步给模型添加行为,以及与领域服务、仓储是怎么交互的 阅读全文
posted @ 2014-08-13 20:00 lawbc 阅读(4170) 评论(19) 推荐(1) 编辑
摘要: jquery.masonry + jquery.infinitescroll 实现瀑布流布局 阅读全文
posted @ 2013-04-26 11:55 lawbc 阅读(9787) 评论(6) 推荐(7) 编辑
摘要: View Code [DllImport( " user32.dll ",CharSet=CharSet.Auto)] public static externIntPtrSendMessage(IntPtrhWnd, intmsg, intwP... 阅读全文
posted @ 2012-11-14 11:01 lawbc 阅读(266) 评论(0) 推荐(0) 编辑
摘要: public static class HttpRequestHelper { private static Encoding DEFAULT_ENCODING = Encoding.UTF8; private static string ACCEPT = "application/json, text/javascript, */*; q=0.01"; ... 阅读全文
posted @ 2012-11-10 13:03 lawbc 阅读(7014) 评论(0) 推荐(0) 编辑
摘要: 12306怎么这么垃圾就不说了,是什么什么毕业生做的也好,老鸟做的也罢,总之bug层出不穷,现在我们就来罗列下吧 1、登录名称格式不正确,提示后按钮看不到,尼玛,叫我后面怎么提交啊,楼下的请列举你看到的bug 阅读全文
posted @ 2012-09-28 13:05 lawbc 阅读(461) 评论(0) 推荐(0) 编辑
点击右上角即可分享
微信分享提示