领域模型的基本构造块:

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领域模型企业级系统(一)的更多相关文章

  1. DDD领域模型企业级系统(二)

    用户层: 1.请求应用层获取用户显示的信息 2.发送命令给应用层要求执行某个命令 应用层: 对用户界面提供各种应用功能(包括信息获取与命令执行),应用层不包含业务逻辑,业务层是由应用层调用领域层(领域 ...

  2. DDD领域模型企业级系统Unity(五)

    添加程序集: 写一个接口: public interface IPlayer { void Play(); } 两个实现类: public class NewPlay : IPlayer { publ ...

  3. DDD领域模型企业级系统Linq的CRUD(四)

    建造一个Product Module类: ProductDBContextDataContext dbcontext = new ProductDBContextDataContext(); publ ...

  4. DDD领域模型企业级系统(三)

    相关代码: public static void ShowArray() { //数据源 int[] arrayas = new int[] { 1, 2, 3, 4 }; //创建查询 var qu ...

  5. DDD领域模型和充血对象

    DDD领域模型 官方说法 领域驱动设计,它是对面向对象的的分析和设计(OOAD,Object Orient Analysis Design)的一个补充,对技术框架进行了分层规划,同时对每个类进行了策略 ...

  6. DDD领域模型系统的工作流(十四)

    在自定义的Windows窗体中运行工作流:(把工作流的代码放入到文本框中) public partial class Form1 : Form { public Form1() { Initializ ...

  7. Nagios:企业级系统监控方案

    在大多数情况下Cacti + RRDtool已经实现对系统各种参数的监测.但很多企业可能不满足于仅仅监测系统基本参数的需求,而是需要监测除基本参数之外的各种应用程序的运行状况.很显然在这种情况下对于一 ...

  8. DDD领域模型之分配权限(十三)

    权限分配和权限查找. 在DDD.Domain工程中新建:BAS_PermissionAssign类 public partial class BAS_PermissionAssgin:Aggreate ...

  9. DDD领域模型数据访问权限之权限(十二)

    实现权限的领域对象:BAS_Permission public partial class BAS_Permission:AggreateRoot { private IRepository<B ...

随机推荐

  1. [python]python安装包错误

    “UnicodeDecodeError: ‘ascii’ codec can’t decode : ordinal not )” 在windows XP上 解决方法: Solution: ====== ...

  2. 题解【bzoj1503 [NOI2004]郁闷的出纳员】

    Description 给出一个下限 \(m\) ,要求维护以下操作 插入一个数(如果小于下限就不加) 给每个数加上一个数 给每个数减去一个数,并且删除掉 \(< m\) 的所有数 求目前第 \ ...

  3. python3.5无法安装pip,报错ImportError: cannot import name 'HTTPSHandler'

    本人系统为:centos6 解决方法: 1  安装openssl yum install openssl 2  安装openssl-devel yum install openssl-devel 3  ...

  4. IntelliJIDEA永久注册使用

    1. 首先下载本地IntelliJIDEA注册服务机(没有密码哦) http://pan.baidu.com/s/1hsyZp0C 2.解压后进入解压的文件夹,找到自己操作系统对应的版本,我这里使用 ...

  5. LINUX 线程

    1.使用进程技术的优势(1)CPU时分复用,单核心CPU可以实现宏观上的并行(2)实现多任务系统需求(多任务的需求是客观的)2.进程技术的劣势(1)进程间切换开销大(2)进程间通信麻烦而且效率低3.解 ...

  6. 面试心得与总结---BAT、网易、蘑菇街

    作者:Xoper.ducky链接:https://www.nowcoder.com/discuss/3043来源:牛客网 之前实习的时候就想着写一篇面经,后来忙就给忘了,现在找完工作了,也是该静下心总 ...

  7. node.js如何让前端请求时能跨域

    1995年,Netscape提出了一个著名的安全策略.现在所有支持JavaScript 的浏览器都会使用这个策略.所谓同源是指,域名,协议,端口相同. 当一个浏览器的两个tab页中分别打开来 百度和谷 ...

  8. TOMCAT添加管理用户认证

    添加配置文件 --原配置文件: # tail -5 /usr/local/tomcat/conf/tomcat-users.xml <user username="tomcat&quo ...

  9. grpc-gateway:grpc转换为http协议对外提供服务

    我所在公司的项目是采用基于Restful的微服务架构,随着微服务之间的沟通越来越频繁,就希望可以做成用rpc来做内部的通讯,对外依然用Restful.于是就想到了google的grpc. 使用grpc ...

  10. 织梦dedecms 模板文件不存在,无法解析文档!

    方法一:[此对应喜欢把模板文件使用".html"的格式,] /include/arc.archives.class.php 556行 if (!preg_match("# ...