DDD领域模型企业级系统(一)
领域模型的基本构造块:
1.实体(Entity):有业务生命周期,使用标识进行跟踪。
2.值对象(Value Object):无业务生命周期,用来描述实体。
3.服务(Service):无状态的行为类型,表示某种能力。
4.聚合(Aggregate):
1).聚合是一簇相关联的对象,出于封装的目的,将这些对象作为一个单元(业务、持久化和并发)。
2).每个聚合都有一个边界和一个根。
3).边界定义了聚合中应该包含什么。
5.聚合根(Aggregate Root)
1).根是聚合中唯一允许被外部引用的元素,在聚合边界内,对象之间可以相互引用。
2).聚合根使用全局标识,由仓储负责其持久化相关的生命周期,实体使用局部标识,由聚合根负责其持久化生命周期。
6.仓储(Repository)
7.工厂(Factory)
聚合的一致性:
1).聚合内的一致性由聚合自身负责维护
2).跨聚合的一致性由服务负责维护
3).最终一致性
如何保证聚合的一致性:
1).对聚合内的任何修改都要经过聚合跟,聚合跟负责一致性检查。
2).聚合内除了聚合根之外的实体只能被临时使用。
3).值对象因为拥有了值语义,天生安全。
4).服务封装跨聚合的一致性职责。
聚合设计的两大准则:
1).聚合不要设计的过大,过大聚合很难保证强一致性
2).聚合与聚合之间不要通过引用的方式来关联,而应该通过ID关联,ID关联具有很好的性能和可伸缩性
3).聚合用来封装真正的不变性,而不是简单将对象组合到一起。
4).聚合之内实体的交互应该通过聚合根完成。
5).应该为一个聚合配备一个仓储。
6).不属于聚合的职责或聚合不具有完成职责所具有的所有信息时,应该交予服务完成或传递另一个聚合根作为参数。
7).聚合内不要依赖领域服务或仓储。
8).永远不要删除聚合根
定义一个接口:IAggreate
public interface IAggreate
{ }
Order类:
public class Order : IAggreate
{
public Guid id { get; set; }
public DateTime datetime { get; set; }
public decimal Total { get; set; }
public OrderItem ordertime { get; set; } public void SetOrderTotal()
{
Total = this.ordertime.LineTotal * 5;
} }
OrderItem订单聚合根:
public class OrderItem
{
public int Amount { get; set; }
public decimal LineTotal { get; set; }
public decimal getproductcurrentprice(Product product)
{
return product.UnitPrice;
}
public decimal PUnitPrice { get; set; } public void SetLineTotal()
{
LineTotal = PUnitPrice * Amount;
}
}
Product 产品表:
public class Product:IAggreate
{
public Guid id { get; set; }
public string Name { get; set; }
public decimal UnitPrice { get; set; } public decimal GetProductPrice()
{
return this.UnitPrice;
}
}
通过服务实现:
public class OPService
{
Product p = new Product();
Order order = new Order();
public void CreateOrder()
{
var punitprice = p.GetProductPrice();
//通过聚合跟赋值
order.ordertime.PUnitPrice = punitprice;
}
}
创建领域对象的方式:
1.直接实例化
2.采用工厂方法进行对象创建
什么时候采用工厂创建领域对象
1.创建领域对象过程复杂,减轻调用方的负担
2.保护领域层领域对象创建逻辑
对象生命周期:

仓储的作用和好处和好处:
1.维护领域对象集合以及状态
2.实现对领域对象的持久化
3.解耦领域对象和数据库,领域层保留仓储的接口,实现领域模型的纯净话
4.可以随时替换仓储的实现,便于单元测试
5.工厂和仓储是都是针对聚合根的
6.一般在应用服务中使用仓储,不建议在领域服务和领域对象中使用仓储,如果必要,则在构造函数中传入仓储接口
代码:
Order类:
/// <summary>
/// 不允许外部访问
/// </summary>
public Guid ID { get; private set; }
public DateTime DateTime { get; private set; } public string OrderSO { get; private set; }
//产品信息
public ProductInfo Product { get; private set; } public Order(string orderso, ProductInfo product)
{
ID = Guid.NewGuid();
DateTime = DateTime.Now;
Product = product;
}
/// <summary>
/// 创建工厂
/// </summary>
public static Order CreateFactory(Guid productid)
{
string orderso = OrderSOService.ProcessOrderNO();
ProductInfo product = (new ProductInfo()).GetProductInfoByKey(productid);
return new Order(orderso, product);
}
产品类:
public class ProductInfo
{
public Guid ID { get; set; }
public string ProductName { get; set; }
public decimal UnitPrice { get; set; } public ProductInfo GetProductInfoByKey(Guid key)
{
return this;
}
}
基础服务层:
public class OrderSOService
{
/// <summary>
/// 产生订单号
/// </summary>
/// <returns></returns>
public static string ProcessOrderNO()
{
return "Orderso";
}
}
服务层:
/// <summary>
/// 服务层
/// </summary>
public class Main
{
Order order = Order.CreateFactory(Guid.NewGuid());
}
DDD领域模型企业级系统(一)的更多相关文章
- DDD领域模型企业级系统(二)
用户层: 1.请求应用层获取用户显示的信息 2.发送命令给应用层要求执行某个命令 应用层: 对用户界面提供各种应用功能(包括信息获取与命令执行),应用层不包含业务逻辑,业务层是由应用层调用领域层(领域 ...
- DDD领域模型企业级系统Unity(五)
添加程序集: 写一个接口: public interface IPlayer { void Play(); } 两个实现类: public class NewPlay : IPlayer { publ ...
- DDD领域模型企业级系统Linq的CRUD(四)
建造一个Product Module类: ProductDBContextDataContext dbcontext = new ProductDBContextDataContext(); publ ...
- DDD领域模型企业级系统(三)
相关代码: public static void ShowArray() { //数据源 int[] arrayas = new int[] { 1, 2, 3, 4 }; //创建查询 var qu ...
- DDD领域模型和充血对象
DDD领域模型 官方说法 领域驱动设计,它是对面向对象的的分析和设计(OOAD,Object Orient Analysis Design)的一个补充,对技术框架进行了分层规划,同时对每个类进行了策略 ...
- DDD领域模型系统的工作流(十四)
在自定义的Windows窗体中运行工作流:(把工作流的代码放入到文本框中) public partial class Form1 : Form { public Form1() { Initializ ...
- Nagios:企业级系统监控方案
在大多数情况下Cacti + RRDtool已经实现对系统各种参数的监测.但很多企业可能不满足于仅仅监测系统基本参数的需求,而是需要监测除基本参数之外的各种应用程序的运行状况.很显然在这种情况下对于一 ...
- DDD领域模型之分配权限(十三)
权限分配和权限查找. 在DDD.Domain工程中新建:BAS_PermissionAssign类 public partial class BAS_PermissionAssgin:Aggreate ...
- DDD领域模型数据访问权限之权限(十二)
实现权限的领域对象:BAS_Permission public partial class BAS_Permission:AggreateRoot { private IRepository<B ...
随机推荐
- Python【logging】模块
# 1.负责往控制台里面输出日志信息的 # 2.往日志文件里面写日志的,按天生成日志,清理日志 import logging from logging import handlers logger = ...
- UIViewController的初始化
UIViewController的初始化一般有两个: -(instancetype)init; -(instancetype)initWithNibName:(NSString *)nibNameOr ...
- 简便开发插件 -- lombok
lombok是一款可以精减java代码.提升开发人员生产效率的辅助工具,可以利用注解在编译期自动生成setter/getter/toString()/constructor代码. 彻底将开发人员从繁琐 ...
- POJ 3308 Paratroopers(最小点权覆盖)(对数乘转加)
http://poj.org/problem?id=3308 r*c的地图 每一个大炮可以消灭一行一列的敌人 安装消灭第i行的大炮花费是ri 安装消灭第j行的大炮花费是ci 已知敌人坐标,同时消灭所有 ...
- Codeforces Round #477 (rated, Div. 2, based on VK Cup 2018 Round 3) D 贪心
http://codeforces.com/contest/967/problem/D 题目大意: 有n个服务器,标号为1~n,每个服务器有C[i]个资源.现在,有两个任务需要同时进行,令他为x1,x ...
- 【精选】Nginx负载均衡学习笔记(一)实现HTTP负载均衡和TCP负载均衡(官方和OpenResty两种负载配置)
说明:很简单一个在HTTP模块中,而另外一个和HTTP 是并列的Stream模块(Nginx 1.9.0 支持) 一.两个模块的最简单配置如下 1.HTTP负载均衡: http { include m ...
- 深入分析Parquet列式存储格式
Parquet是面向分析型业务的列式存储格式,由Twitter和Cloudera合作开发,2015年5月从Apache的孵化器里毕业成为Apache顶级项目,最新的版本是1.8.0. 列式存储 列式存 ...
- xgraph和gnuplot初体验
今天分别体验了一下xgraph和gnuplot. xgraph是ns2自带的画图工具,使用很简单.它的标准的数据文件是ascii文本文件,每一行两个数据,以空格隔开,这样就有了两列数据.把这样的文 ...
- NameValuePair方式传参数
今天工作中联调外部的一个接口用post方式传输,我按照文档封装参数成Jason字符串传入,但是对方一直接受参数为空,折腾了半天也没找到问题.很苦恼,检查代码都没有错误,可是为什么对方接受参数为空呢?然 ...
- 查看GCC的内置宏定义
开发过程中我们常常需要使用宏定义.. 为了尽可能多的使用GCC为我们提供的特性,首先我们需要知道gcc提供了那些特性... gcc -dM -E - < /dev/null 没错,就这么一句话就 ...