当前位置: 首页 > 编程日记 > 正文

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,}
}

转载于:https://www.cnblogs.com/liubiaocai/p/3938192.html

相关文章:

C#用 SendKyes 结合 Process 或 API FindWindow、SendMessage(PostMessage) 等控制外部程序

Win32 平台是 消息驱动模式.Net 框架是 事件驱动模式标题所指的 “控制外部程序”&#xff0c;外部程序是指与本程序无内在相关性的另外一个程序 基于上面提到的&#xff0c;对于.NET的winform程序&#xff0c;在默认情况下&#xff08;即未对接收消息的事件做自定义处理&#…

springMVC swagger2

参考地址&#xff1a;https://www.cnblogs.com/exmyth/p/7183753.html https://blog.csdn.net/programmer_sean/article/details/72236948 1. maven 依赖 <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId&…

1061 Dating

笔记&#xff1a; 第一个输出根据的是大写字母 第二个输出根据的是0-9andA-N 第三个输出根据的是大写字母和小写字母 知道范围便方便确定边界 两两比对时&#xff0c;先遍历一个字符串&#xff0c;遇到在范围内的字符&#xff0c;看其和第二个字符串同位置的字符是否相等 …

PA 项目创建任务

---- 创建任务 DECLAREp_project_id NUMBER : 155233;p_task_number VARCHAR2(240) : CXYTEST0001;p_task_name VARCHAR2(240) : 接口测试CXYTEST0001;p_task_description VARCHAR2(240) : TASKCXYTEST0001;p_scheduled_start_date DAT…

SSM登陆拦截器实现

首先在springmvc中配置拦截器 <!-- 配置拦截器 --><mvc:interceptors><mvc:interceptor><!-- 拦截所有mvc控制器 --><mvc:mapping path"/**"/><!-- mvc:exclude-mapping是另外一种拦截&#xff0c;它可以在你后来的测试中对某个页面…

AGG 学习笔记

我了解的&#xff21;&#xff27;&#xff27;的总体结构按照文件大致分为&#xff1a;   &#xff11;&#xff09;基本定义&#xff08;config,basics....)&#xff1b;   &#xff12;&#xff09;基本操作、类型&#xff08;主要供&#xff21;&#xff27;&#xff2…

1073 Scientific Notation

笔记&#xff1a;这是我迄今为止写过的最复杂的字符串处理算法题。 收获&#xff1a;分而治之&#xff0c;想不清楚就自己设计测试用例和结果。列举然后归类。 以下是程序流程图 #include<cstdio> #include<cmath> #include<cstring> #include<algorith…

几个笔试题目总结

1、阿里某个笔试题&#xff0c;两个字符串text&#xff0c;query&#xff0c;找到text中包含的最长的query的字串&#xff1a; public static String subStr(String text, String query) {if (text ! null && query ! null) {int length query.length();for (int i 0…

baidu mp3竟然还加密,太扯了

baidu mp3竟然还加密&#xff0c;太扯了 public class BaiduHelper { static int F 0; static string I "", J ""; static string O ""; static string E ""; static int[] K new int[1000…

Ubuntu 之linux与windows互传文件

Windows系统下与linux传输文件 windows环境下&#xff0c;windows传出数据到linux下 确保ubuntu安装了ssh服务端。如果没有安装&#xff0c;使用以下命令安装&#xff1a; sudo aptget install ssh service sshd restart 2.windows下下载pscp.exe软件从PuTTY官方网站下载pscp.e…

1048 数字加密 --非满分

16/20 非满分&#xff0c;待来日复习双指针再分析原因 #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<bits/stdc.h> using namespace std;void reverStr(char str[]){int len strlen(str);for(int i0;i&l…

端到端对话模型新突破!Facebook发布大规模个性化对话数据库

作者&#xff5c;Pierre-Emmanuel Mazare 等译者&#xff5c;郝毅编辑&#xff5c;Debra出处丨 AI 前线AI 前线导读&#xff1a;聊天机器人是目前非常流行的一种人工智能系统。目前大部分聊天机器人的衔接性都不是很好&#xff0c;尤其是在没有主动的重调优策略下训练出的端到端…

上传文件大小的配置Webcong

修改Webcong文件:<system.web><httpRuntime maxRequestLength"40690" useFullyQualifiedRedirectUrl"true" executionTimeout"6000" useFullyQualifiedRedirectUrl"false" minFreeThreads"…

1001 A+B Format

由于逗号的有无是从末尾数起&#xff0c;满足三个数(且高位还有数)就加逗号&#xff0c;所以有必要把字符串反转&#xff0c;然后寻找数组下标和3的关系 #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace st…

[转]数据库建立索引的一般依据

建立索引常用的规则如下&#xff1a; 1、表的主键、外键必须有索引&#xff1b; 2、数据量超过300的表应该有索引&#xff1b; 3、经常与其他表进行连接的表&#xff0c;在连接字段上应该建立索引&#xff1b; 4、经常出现在Where子句中的字段&#xff0c;特别是大表的字段&…

为图片添加半透明遮罩效果

平时为图片添加半透明遮罩效果&#xff0c;我的做法如下&#xff1a;利用标签i实现背景半透明遮罩。当鼠标hover时, 提高i的背景色透明度值background-color: rgba(0, 0, 0, .6) <p class"opacity-black-position"><a href"#"><img src&quo…

linux下typora安装

# optional, but recommended sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys BA300B7755AFCFAE# add Typoras repository sudo add-apt-repository deb https://typora.io ./linux/ sudo apt-get update# install typora sudo apt-get install typora

1005 Spell It Right

基本步骤是&#xff1a;100位的数字longlong也存不下&#xff0c;作为字符串读入&#xff0c;对字符串进行遍历&#xff0c;每个字符减去0加到总和sum上&#xff0c;再将整形的总和sum转化为字符串&#xff0c;对得到的字符串进行遍历&#xff0c;将每个字符映射到英文单词上。…

C#多线程学习(四) 多线程的自动管理(线程池) (转载系列)——继续搜索引擎研究...

在多线程的程序中&#xff0c;经常会出现两种情况&#xff1a; 一种情况&#xff1a; 应用程序中&#xff0c;线程把大部分的时间花费在等待状态&#xff0c;等待某个事件发生&#xff0c;然后才能给予响应 这一般使用ThreadPool&#xff08;线程池&#xf…

使用Node.js快速搭建WebSocket server

原文地址&#xff1a;http://my.oschina.net/yushulx/blog/309413 目录[-] 安装服务端客户端参考安装 ?1npm install ws服务端 server.js ?12345678var WebSocketServer require(ws).Server, wss new WebSocketServer({port: 8080});wss.on(connection, function(ws) {ws.o…

android采用MVP完整漫画APP、钉钉地图效果、功能完善的音乐播放器、仿QQ动态登录效果、触手app主页等源码...

Android精选源码 一个可以上拉下滑的Ui效果&#xff0c;觉得好看可以学学 APP登陆页面适配 一款采用MVP的的完整漫画APP源码 android实现钉钉地图效果源码 一个使用单个文字生成壁纸图片的app android 仿QQ动态背景登录效果源码 功能完善的Android 手机本地音乐文件播放器 andr…

1035 Password

很适合用结构体数组的一道题 #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std;struct info{char usr[11]"";char pwd[11]"";bool changed false; }infos[1010];int main(){int n,…

Android -- DrawerLayout

抽屉效果的导航菜单 喜欢知乎的都应该装的用知乎日报吧~这里指Android的不是IOS的。知乎日报的导航菜单就是用DrawerLayout实现的。 觉得这种侧滑的抽屉效果的菜单很好。 不用切换到另一个页面&#xff0c…

Socketserver 笔记

引入Socketserver的背景&#xff1a;我们之前使用socket编程的时候&#xff0c;Server端创建一个连接循环&#xff08;建立连接&#xff09;一个通信循环&#xff08;基于一次连接建立通信循环&#xff09;&#xff0c;&#xff08;这里的黏包问题我们的实现方式是&#xff1a;…

Delphi 调用C#编写的WebService 参数为Null解决方法

今天测试.net 2.0的WebService&#xff0c;发现了一个大问题。就是无法获取参数&#xff0c;参数永远是null。当然了使用.net调用 没有任何问题&#xff0c;web测试页也正常。不论是Delphi7还是java调用的结果的都是一样的&#xff0c;难道是.net 2.0的Bug&#xff1f; 测试结…

1025 PAT Ranking

1. 考生的编号是数字字符串&#xff0c;但是没必要转化成整数再比较&#xff0c;可以直接用strcmp() 2. 对整体的排名进行编号时所有信息都已经齐备&#xff0c;可以边编号边输出 3. 需要有些思量的地方是部分编号&#xff0c;当当前学生的分数不等于他上一个该怎么办 4. 真…

C#编写的多生产者多消费者同步问题

// 多个生产者和多个消费者&#xff0c;能生产n个产品的情况using System; using System.Threading;public class HoldIntegerSynchronized{private int[] buffer; //缓冲区private int occupiedBufferCount 0;private int readPosition 0 , writePosition 0;//下一个读到的…

展望2009,回眸2008

2008年真正的过去了&#xff0c;已经感觉不到2008年的存在。 2009年来了&#xff0c;似乎真正的来了。 生活的压力更大了&#xff0c;工作也不太顺利。 希望越来越好&#xff0c;也不知道是不是真的该跳槽了。 待在这里很郁闷。 转载于:https://www.cnblogs.com/tacker/archive…

m_Orchestrate learning system---七、如何快速学好前端

m_Orchestrate learning system---七、如何快速学好前端 一、总结 一句话总结&#xff1a;看视频啊&#xff0c;系统看视频啊 1、如何解决单词数字太长超出边界的问题&#xff1f; word-wrap 把编辑删除都挤跑了 2、amaze ui中a标签和button标签可以互换么&#xff1f; 其实弄上…

1062 Talent and Virtue

1.在结构体里面设置total_grades属性是明智之举&#xff0c;但是不可以在结构体内得到total_gradesvirtue_gradetalent_grade; 2.弄清题意&#xff0c;对人进行分类&#xff0c;等级越高type值越小&#xff0c;但是注意分的类别也许出现交叉的情况&#xff0c;细的要出现在粗的…