• DDD领域驱动设计之聚合、实体、值对象


    关于具体需求,请看前面的博文:DDD领域驱动设计实践篇之如何提取模型,下面是具体的实体、聚合、值对象的代码,不想多说什么是实体、聚合等概念,相信理论的东西大家已经知晓了。本人对DDD表示好奇,没有在真正项目实践过,甚至也没有看过真正的DDD实践的项目源码,处于极度纠结状态,甚至无法自拔,所以告诫DDD爱好者们,如果要在项目里面实践DDD,除非你对实体建模和领域职责非常了解(很多时候会纠结一些逻辑放哪里好,属于设计问题)以及你的团队水平都比较高认同DDD,否则请慎重。。。勿喷!

    代码在后,请先看DEMO结果图

    1、聚合的基类,注意,几乎属性都是拼音首字母命名,勿喷哈,不要跑题!

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using DDD.Infrastructure;
    using DDD.Infrastructure.Domain;
    
    namespace DDD.Domain
    {
        /// <summary>
        /// 项目基类
        /// </summary>
        public abstract class ProjectBase : EntityBase, IAggregateRoot
        {
            protected ProjectBase()
            {
                this.ND = DateTime.Now.Year;
                this.CJSJ = DateTime.Now;
                this.WH = new DocumentNumber();
            }
    
            /// <summary>
            /// 安排批次
            /// </summary>
            public int APPC { get; set; }
            /// <summary>
            /// 项目名称
            /// </summary>
            public string XMMC { get; set; }
            /// <summary>
            /// 项目编号
            /// </summary>
            public string XMBH { get; internal set; }
            /// <summary>
            /// 年度
            /// </summary>
            public int ND { get; set; }
            /// <summary>
            /// 文号
            /// </summary>
            public DocumentNumber WH { get; set; }
            /// <summary>
            /// 创建时间
            /// </summary>
            public DateTime CJSJ { get; set; }
            /// <summary>
            /// 下发行政区名称
            /// </summary>
            public string XFXZQMC { get; set; }
            /// <summary>
            /// 下发行政区代码
            /// </summary>
            public string XFXZQDM { get; set; }
            /// <summary>
            /// 行政区名称
            /// </summary>
            public string XZQMC { get; set; }
            /// <summary>
            /// 行政区代码
            /// </summary>
            public string XZQDM { get; set; }
            /// <summary>
            /// 备注
            /// </summary>
            public string BZ { get; set; }
            /// <summary>
            /// 指标级别
            /// </summary>
            public IndicatorGrade ZBJB { get; set; }
            /// <summary>
            /// 附件id
            /// </summary>
            public decimal ATTACHID { get; set; }
            /// <summary>
            /// 项目状态
            /// </summary>
            public ProjectStauts Status { get; set; }
    
            /// <summary>
            /// 业务代码
            /// </summary>
            protected abstract string BussinessCode { get; }
    
            /// <summary>
            /// 登记
            /// </summary>
            /// <param name="seq"></param>
            public virtual void Register()
            {
                this.XMBH = this.BussinessCode + SeqGeneratr.Generate();
            }
    
            /// <summary>
            /// 是否可以更新或者删除
            /// </summary>
            /// <returns></returns>
            public virtual bool CanUpdate()
            {
                return this.ZBJB == IndicatorGrade.Country || this.XFXZQDM == this.XZQDM || this.Status == ProjectStauts.Default;
            }
    
            public void Send()
            {
                this.Status = ProjectStauts.Sent;
            }
        }
    }
    

    2、聚合1

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using DDD.Infrastructure;
    using DDD.Infrastructure.Domain;
    
    namespace DDD.Domain.Indicator
    {
        /// <summary>
        /// 计划指标
        /// </summary>
        public class PlanIndicator : ProjectBase
        {
            public PlanIndicator()
            {
                IndicatorArea = new IndicatorArea();
            }
    
            protected override string BussinessCode
            {
                get { return "103101"; }
            }
    
            /// <summary>
            /// 指标面积
            /// </summary>
            public IndicatorArea IndicatorArea
            {
                get;
                set;
            }
    
            public override IEnumerable<BusinessRule> Validate()
            {
                if (this.IndicatorArea.GD > this.IndicatorArea.NYD)
                {
                    yield return new BusinessRule("IndicatorArea.GD", "耕地面积不能大于农用地面积");
                }
            }
    
            public override void Register()
            {
                if (this.ZBJB == IndicatorGrade.Country)
                {
                    this.Send();
                }
                base.Register();
            }
        }
    }
    

    3、聚合2

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using DDD.Infrastructure;
    using DDD.Infrastructure.Domain;
    
    namespace DDD.Domain.Arrange
    {
        /// <summary>
        /// 计划安排
        /// </summary>
        public class PlanArrange : ProjectBase
        {
            public PlanArrange()
            {
                JHSY = new IndicatorArea();
                SJSY = new IndicatorArea();
            }
    
            protected override string BussinessCode
            {
                get { return "103102"; }
            }
    
            /// <summary>
            /// 计划使用面积
            /// </summary>
            public IndicatorArea JHSY
            {
                get;
                set;
            }
    
            /// <summary>
            /// 实际使用面积
            /// </summary>
            public IndicatorArea SJSY
            {
                get;
                set;
            }
    
            /// <summary>
            /// 剩余面积
            /// </summary>
            public IndicatorArea SY
            {
                get
                {
                    return JHSY - SJSY;
                }
            }
    
            /// <summary>
            /// 用地类别
            /// </summary>
            public string XMYDLB { get; set; }
    
            public override IEnumerable<BusinessRule> Validate()
            {
                if (this.JHSY.GD > this.JHSY.NYD)
                {
                    yield return new BusinessRule("JHSY.GD", "计划使用中,耕地面积不能大于农用地面积");
                }
                if (this.SJSY.GD > this.SJSY.NYD)
                {
                    yield return new BusinessRule("SJSY.GD", "实际使用中,耕地面积不能大于农用地面积");
                }
                if (string.IsNullOrEmpty(this.XMYDLB))
                {
                    yield return new BusinessRule("XMYDLB", "项目用地类别不允许为空");
                }
            }
        }
    }
    

    4、值对象1

    using System;
    using DDD.Infrastructure.Domain;
    
    namespace DDD.Domain
    {
        /// <summary>
        /// 文号
        /// </summary>
        public class DocumentNumber : ValueObject<DocumentNumber>, ICloneable
        {
            public static readonly string LeftYearChar = "〔";
            public static readonly string RightYearChar = "〕";
    
            public DocumentNumber() 
            {
                
            }
    
            public DocumentNumber(string wh) 
            {
                try
                {
                    this.Code = wh.Substring(0, wh.IndexOf(LeftYearChar));
                    this.Year = wh.Substring(wh.IndexOf(LeftYearChar), wh.IndexOf(RightYearChar) - this.Code.Length + 1);
                    this.Order = wh.Replace(this.Code + this.Year, "");
                    this.Year = this.Year.Replace(LeftYearChar, "").Replace(RightYearChar, "");
                }
                catch(Exception ex)
                {
                    throw new InvalidCastException("文号格式不正确", ex);
                }
            }
    
            /// <summary>
            /// 发文机关代字
            /// </summary>
            public string Code { get; set; }
            /// <summary>
            /// 年份
            /// </summary>
            public string Year { get; set; }
            private string order;
            /// <summary>
            /// 顺序号
            /// </summary>
            public string Order
            {
                get
                {
                    if (!string.IsNullOrEmpty(order) && !order.Contains("号"))
                    {
                        order += "号";
                    }
                    return order;
                }
                set
                {
                    order = value;
                }
            }
    
            public override string ToString()
            {
                if (string.IsNullOrEmpty(Code) && string.IsNullOrEmpty(Year) && string.IsNullOrEmpty(order))
                {
                    return string.Empty;
                }
                return this.Code + LeftYearChar + Year + RightYearChar + Order;
            }
    
            public static implicit operator DocumentNumber(string wh)
            {
                return new DocumentNumber(wh);
            }
    
            public object Clone()
            {
                return this.MemberwiseClone();
            }
        }
    }

    5、值对象2

    using DDD.Infrastructure;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using DDD.Infrastructure.Domain;
    
    namespace DDD.Domain
    {
        /// <summary>
        /// 指标面积
        /// </summary>
        public class IndicatorArea : ValueObject<IndicatorArea>
        {
            /// <summary>
            /// 新增建设用地
            /// </summary>
            public decimal XZJSYD
            {
                get
                {
                    return NYD + WLYD;
                }
            }
            /// <summary>
            /// 农用地
            /// </summary>
            public decimal NYD { get; set; }
            /// <summary>
            /// 耕地
            /// </summary>
            public decimal GD { get; set; }
            /// <summary>
            /// 未利用地
            /// </summary>
            public decimal WLYD { get; set; }
    
            /// <summary>
            /// 将公顷转换成亩
            /// </summary>
            /// <returns></returns>
            public IndicatorArea HectareToMu()
            {
                return new IndicatorArea
                {
                    GD = this.GD * 15,
                    NYD = this.NYD * 15,
                    WLYD = this.WLYD * 15,
                };
            }
    
            /// <summary>
            /// 重载加法运算符
            /// </summary>
            /// <param name="a"></param>
            /// <param name="b"></param>
            /// <returns></returns>
            public static IndicatorArea operator +(IndicatorArea a, IndicatorArea b)
            {
                return new IndicatorArea
                {
                    GD = a.GD + b.GD,
                    NYD = a.NYD + b.NYD,
                    WLYD = a.WLYD + b.WLYD,
                };
            }
    
            /// <summary>
            /// 重载减法运算符
            /// </summary>
            /// <param name="a"></param>
            /// <param name="b"></param>
            /// <returns></returns>
            public static IndicatorArea operator -(IndicatorArea a, IndicatorArea b)
            {
                return new IndicatorArea
                {
                    GD = a.GD - b.GD,
                    NYD = a.NYD - b.NYD,
                    WLYD = a.WLYD - b.WLYD,
                };
            }
    
            public static IndicatorArea Sum(IEnumerable<IndicatorArea> query)
            {
                return new IndicatorArea
                {
                    GD = query.Sum(t => t.GD),
                    NYD = query.Sum(t => t.NYD),
                    WLYD = query.Sum(t => t.WLYD),
                };
            }
        }
    }
    

      

    6、枚举

    using System.ComponentModel;
    
    namespace DDD.Domain
    {
        /// <summary>
        /// 指标级别
        /// </summary>
        public enum IndicatorGrade
        {
            /// <summary>
            /// 国家
            /// </summary>
            [Description("国家")]
            Country,
            /// <summary>
            /// 省级
            /// </summary>
            [Description("省级")]
            Province,
            /// <summary>
            /// 市级
            /// </summary>
            [Description("市级")]
            City,
            /// <summary>
            /// 县级
            /// </summary>
            [Description("县级")]
            County,
        }
    }
    
    using System.ComponentModel;
    
    namespace DDD.Domain
    {
        /// <summary>
        /// 项目状态
        /// </summary>
        public enum ProjectStauts
        {
            /// <summary>
            /// 默认状态,已登记
            /// </summary>
            Default,
            /// <summary>
            /// 已下发
            /// </summary>
            Sent,
        }
    }
    

      

      

  • 相关阅读:
    学习完java基础,总结的一些东西,希望大佬们茶余饭后看看,如有错误还请指正
    JDK和JRE的简单概述
    堆排序
    mybatis的一级缓存
    重用执行器和批处理执行器
    JDBC statement和mybatis mapper statement
    深入浅出Mybatis技术原理与实战(杨开振)(带详细书签) PDF 下载 高清 完整版+源码
    mybatis执行器1
    mybatis执行器1---简单描述JDBC
    JDBC不再需要Class.forName()来显式加载jdbc驱动
  • 原文地址:https://www.cnblogs.com/liubiaocai/p/3938192.html
Copyright © 2020-2023  润新知