领域层的服务
在第二节已基本介绍过服务的作用了领域层服务的作用主要是为了解决业务上的逻辑问题更多的时候服务是一个与业务相关的动作。比如在上述例子中在Order表里记录的是每次交易的过程每次商品的送货费Freightage为10元当商品价格Price超过98元可免费送货当用户 Person积分Point超过2000分可获7折优惠Favorable1000~2000分可获8折1000分以下可有9折最后总体价 格为为TotalPrice。这复杂的业务逻辑完全可以由一个领域服务类AccountManager来完成namespace Business.Service.DomainService { public class AccountManager { private Person _person; private Order _order; public AccountManager(Person person, Order order) { _person person; _order order; } ///计算总体收费 public void Account() { //计算商品数量 GoodsCount(); //计算商品价格 PriceAccount(); //计算优惠等级 FavorableAccount(); double price1 (_order.Price - _order.Favorable).Value; //计算运费 FreightageAccount(price1); //计算总体价费 _order.TotalPrice price1 _order.Freightage.Value; } //计算商品数量 private void GoodsCount() { _order.Count0; foreach (var OrderItem in _order.OrderItem) _order.Count OrderItem.Count; } //商品总体价格 private void PriceAccount() { _order.Price 0; foreach (var OrderItem in _order.OrderItem) _order.Price OrderItem.Price * OrderItem.Count; } //优惠分为三等积分小于1000有9折小于2000分为8折大于2000为7折 private void FavorableAccount() { int point (int)_person.Point.GetInt(); if (point 1000) _order.Favorable _order.Price * 0.1; if (point 1000 point 2000) _order.Favorable _order.Price * 0.2; if (point 2000) _order.Favorable _order.Price * 0.3; } //如果价格在98元以上可免运费。其余运费为10元 private void FreightageAccount(double price) { if (price 98) _order.Freightage 0; else _order.Freightage 10; } } }你可能会说在这个业务流程中除了积分优惠Person.Point以外其他的业务都只与Order的属性有关按照充血型模型的方案完全可以把这些业务放到Order的方法当中而把积分优惠独立成为一个服务。但在下在很多的开发过程中发现为模型附上动作会带来一连串的问题好像你不知道哪些操作应该在模型动作上实现哪里应该在服务中实现......。对于这些无休止的争论不会因为这里的一个小例子而停止但在这里我会坚持使用贫血型模型,利用服务来完成所有的动作。再举一个例子在最后结单的时候Order表里会产生订单号码OrderNumber和下订日期DeliveryPerson表的积分也会加上订单总价的点数。对应这个操作也可以单独开发一个PaymentManager服务类进行管理。namespace Business.Service.DomainService { public class PaymentManager { //下单结算 public void Payment(Order order,Person person) { //确定下单建立订单号 order.OrderNumber Guid.NewGuid().ToString(); order.Delivery DateTime.Now; //增加积分 if (person.Point.HasValue) person.Point (int)order.TotalPrice.GetValueOrDefault(); else person.Point (int)order.TotalPrice.GetValueOrDefault(); } } }利用领域层的服务使得每个Manager服务类的职能非常明确业务管理起来也十分地方便领域层可以随着业务的改变而灵活变动。而且领域层具有 “高内聚低耦合” 特性它并不依赖其它任何一层而只是把业务逻辑包含在里面。回到目录六、工厂模式FactoryFactory是常用到软件开发模式在网上像简单工厂、工厂方法、抽象工厂等开发模式的资料都到处可寻可这并不是领域驱动设计的主题。在这一节里我主要想介绍Factory的适用时机。并非生成所有对象的时候都需要用到工厂模式。在生成简单对象的时候可以直接利用构造函数来代替工厂也可以添加工厂方法来生成对象。但如果在生成对象时内部属性之间存在一系统复杂的业务规则的时候就可以把生成方法独立到一个Factory类里面。这时候客户端无需理会潜在逻辑关系而直接通过这个Factory来生成相应的对象。举个例子在新建Order的时候业务上规定运费是总体金额的1%折扣规定是7.5折...... 。如果由客户端新建一个对象Order然后为这些属性负值那相关的业务逻辑就会暴露在外。这时候就可以使用Factory模式把属性之间的关系封装到Factory之内客户端通过Factory就能轻松地生成Order对象而无需要理会复杂的内部关系。至于较复杂的Factory模式在此不多作介绍各位可以在网上查找相关资料。回到目录七、细说应用层1. SOA系统中应用层的特点在开发SOA分布式系统的时候应用层是一个重点它主要有两个作用。第一应用层主要作用是协调领域层工作指挥领域对象解决业务问题但应用层本身不会牵扯到业务状态。第二在SOA系统当中应用层是数据运输中心和信息发放的端口担负着数据转换与数据收发的责任。它有以下的特点粗粒度分布式系统与普通网站和应用程序不同因为它假定外界对系统内部是毫无了解的用户只想输入相关数据最后得到一系列计算结果。所以我们应该把计算结果封装在一个数据传输对象DTO内实现粗粒度的传递这是一般项目与SOA系统在服务层的一个最明显的差别。 想想如果一个页面需要同时显示一个顾客的个人资料、某张订单的详细资料那将要同时获取Person、Order、OrderItem三张表的信息。在普通系统的开发过程中这并不会造成太大问题但在使用远程服务的时候如果用三个方法分别获取那将会造成不少的性能损耗。特别是在分布式开发系统中应用层与表现层之间是实现分离的更多时候两者是由不同部门所开发的模块表现层不会了解应用层中的逻辑关系PersonOrderOrderItem三样东西在表现层看来也就是同一样东西那就是返回值。所以在系统内应该把多张表的信息封装在一个DTO对象内通过应用层一个远程方法一次性返还。使用粗粒度的数据元素是分布式系统的一个特点。传输性如果你熟悉SOA系统对DTOData Transfer Object 数据传输对象这个词一定并不陌生。DTO属于一个数据传输的载体内部并不存在任何业务逻辑通过DTO可以把内部的领域对象与外界隔离。DTO所封装的是客户端的数据所以它的设计更多地是针对客户端的需求而不是业务逻辑。比如说本来Person与Order是一对多的关系但当一个页面只要显示的是一个客户的单张订单信息那我们就可以根据需要把DTO中的Person和Order设计为一对一的关系。如果你是使用MVC开发一般的网站更多时候会把返回对象直接转化为Model。如果你开发是一个分布式系统那更多时候会从系统性能与隐藏业务逻辑出发着想。而且考虑到把内部对象转化为DTO将是一件麻烦的事建议应该考虑DTO的兼容性使DTO可以作为多个方法的返还载体。注意在SOA系统内应该从性能出发优先考虑粗粒度元素的传输性问题封装性在SOA系统当中应用层服务的发布并不需要复杂的模型只需使用外观模式Facade把一些功能封装在少数的几个服务类里面使用Web Service、TCP/IP套接字、MSMQ等服务方式向外界发布。说到这里我真的十分感激Martin先生带给我的帮助在开发过程中这些复杂的问题带给我不少的困扰Martin先生一纸富有经验的独特见解真的带给在下很大的启发。2. 应用层的协调性应用层服务会利用Repository完成实体基本的插入、更新、获取等等操作并调用领域层的服务管理的业务逻辑。注意观察一切的业务逻辑都只会隐藏于领域层应用层服务只起着协调作用本身不应该包含有任何业务逻辑。可以看到OrderService就是通过调用AccountManager、PaymentManager等领域层服务来完成结账、付款等一系列复杂业务逻辑的。namespace Business.Service.ApplicationService { public class PersonService { private IPersonRepository personRepository DataAccess.CreatePersonRepository(); public int AddPerson(Person person) { return personRepository.AddPerson(person); } public int UpdatePerson(Person person) { return personRepository.UpdatePerson(person); } public Person GetPerson(int personID) { return personRepository.GetPerson(personID); } public IListPerson GetList() { return personRepository.GetList(); } } public class OrderService { private IOrderRepository orderRepository DataAccess.CreateOrderRepository(); public int AddOrder(Order order) { //计算Order总体费用 Account(order); //加入修改后的Order return orderRepository.AddOrder(order); } //调用领域层服务AccountManager计算Order总体费用 private void Account(Order order) { //获取对应Person对象 IPersonRepository personRepository DataAccess.CreatePersonRepository(); Person person personRepository.GetPerson(order.PersonID); //调用服务层的AccountManager对象计算费用修改Order AccountManager accountManager new AccountManager(person, order); accountManager.Account(); } //调用领域层服务PaymentManager确认订单 public Order Payment(int orderID) { var orderorderRepository.GetOrder(orderID); if (order ! null) { PersonRepository personRepository new PersonRepository(); var personpersonRepository.GetPerson(order.PersonID); PaymentManager paymentManager new PaymentManager(); paymentManager.Payment(order, person); orderRepository.UpdateOrder(order); personRepository.UpdatePerson(person); return order; } else throw new Exception(Can not find order!); } public int DeleteOrder(Order order) { return orderRepository.DeleteOrder(order.ID); } public Order GetOrder(int orderID) { return orderRepository.GetOrder(orderID); } public IListOrder GetList() { return orderRepository.GetList(); } public IListOrder GetListByPerson(int personID) { return orderRepository.GetListByPerson(personID); } public int UpdateOrder(Order order) { Account(order); return orderRepository.UpdateOrder(order); } public int AddOrderItem(OrderItem orderItem) { int index orderRepository.AddOrderItem(orderItem); Order order orderRepository.GetOrder(orderItem.OrderID); UpdateOrder(order); return index; } public int DeleteOrderItem(OrderItem orderItem) { int index orderRepository.DeleteOrderItem(orderItem.ID); Order order orderRepository.GetOrder(orderItem.OrderID); UpdateOrder(order); return index; } ....................... ....................... } }

相关新闻

LitCAD:15分钟从零基础到二维CAD绘图高手

LitCAD:15分钟从零基础到二维CAD绘图高手

LitCAD:15分钟从零基础到二维CAD绘图高手 【免费下载链接】LitCAD A very simple CAD developed by C#. 项目地址: https://gitcode.com/gh_mirrors/li/LitCAD 想要掌握专业级的CAD绘图技能,却担心软件复杂、学习曲线陡峭?LitCAD正是为…

2026/7/5 4:51:39阅读更多 →
LangGraph快速入门与底层原理剖析

LangGraph快速入门与底层原理剖析

LangGraph 以图的方式构建语言代理 官方文档地址:https://langchain-ai.github.io/langgraph/ LangGraph 是一个用于构建具有 LLMs 的有状态、多角色应用程序的库,用于创建代理和多代理工作流。与其他 LLM 框架相比,它提供了以下核心优势&…

2026/7/5 4:51:39阅读更多 →
如何在Apple Silicon Mac上轻松运行Windows应用:Whisky终极指南

如何在Apple Silicon Mac上轻松运行Windows应用:Whisky终极指南

如何在Apple Silicon Mac上轻松运行Windows应用:Whisky终极指南 【免费下载链接】Whisky A modern Wine wrapper for macOS built with SwiftUI 项目地址: https://gitcode.com/gh_mirrors/wh/Whisky 想在Apple Silicon Mac上无缝运行Windows软件和游戏吗&am…

2026/7/5 4:51:39阅读更多 →
AAA小学期第五周学习笔记

AAA小学期第五周学习笔记

完成了发射端pcb的绘制,并下单

2026/7/5 6:01:43阅读更多 →
如何在3分钟内配置专业级DeepL翻译浏览器扩展

如何在3分钟内配置专业级DeepL翻译浏览器扩展

如何在3分钟内配置专业级DeepL翻译浏览器扩展 【免费下载链接】deepl-chrome-extension A DeepL Translator Chrome extension 项目地址: https://gitcode.com/gh_mirrors/de/deepl-chrome-extension 还在为语言障碍而烦恼吗?想要像阅读母语一样轻松浏览外文…

2026/7/5 6:01:43阅读更多 →
AI For Everyone 课程 2024 版:非技术视角的 4 周 AI 项目实战路线图

AI For Everyone 课程 2024 版:非技术视角的 4 周 AI 项目实战路线图

AI For Everyone 课程 2024 版:非技术视角的 4 周 AI 项目实战路线图当零售业高管Sarah第一次听到董事会要求"全员拥抱AI"时,她盯着满屏的技术术语感到无所适从。这正是《AI For Everyone》课程要解决的核心痛点——在不需要理解神经网络架构的…

2026/7/5 6:01:43阅读更多 →
DeepL Chrome翻译插件:5分钟掌握专业级网页翻译工具

DeepL Chrome翻译插件:5分钟掌握专业级网页翻译工具

DeepL Chrome翻译插件:5分钟掌握专业级网页翻译工具 【免费下载链接】deepl-chrome-extension A DeepL Translator Chrome extension 项目地址: https://gitcode.com/gh_mirrors/de/deepl-chrome-extension 还在为阅读外文网页而烦恼吗?DeepL Chr…

2026/7/5 6:01:43阅读更多 →
Adobe-GenP 3.0完全指南:三步解锁Adobe全家桶专业功能

Adobe-GenP 3.0完全指南:三步解锁Adobe全家桶专业功能

Adobe-GenP 3.0完全指南:三步解锁Adobe全家桶专业功能 【免费下载链接】Adobe-GenP Adobe CC 2019/2020/2021/2022/2023 GenP Universal Patch 3.0 项目地址: https://gitcode.com/gh_mirrors/ad/Adobe-GenP 对于众多创意工作者来说,Adobe Creati…

2026/7/5 6:01:43阅读更多 →
错题本为什么常常没有效果

错题本为什么常常没有效果

很多孩子都有错题本,但真正因为错题本明显改善学习质量的并不多。原因很简单:很多错题本只是把错题抄了一遍,或者把答案改对了,并没有真正修复错因。孩子今天把这道题改会了,下次换一个条件、换一个问法,还…

2026/7/5 5:56:43阅读更多 →
从GitHub安全案例解析常见漏洞与防护实践

从GitHub安全案例解析常见漏洞与防护实践

1. 项目概述:从GitHub Trending看安全实战 最近在GitHub Trending上看到一个项目,叫 skills4/skills ,它因为一些安全漏洞案例被大家讨论。这其实是一个挺典型的场景:一个旨在展示或教授某种技能的仓库,本身却成了安…

2026/7/5 0:01:08阅读更多 →
MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

# MLT 2026启示:因果推理与概率建模驱动下一代LLM应用## 一、背景与挑战:从“黑箱预测”到“可信推理”2026年6月,第7届机器学习与趋势国际会议(MLT 2026)将在悉尼召开。会议议程中,“因果与可解释机器学习…

2026/7/5 0:01:08阅读更多 →
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时,通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中,是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

2026/7/5 0:01:08阅读更多 →
从GitHub安全案例解析常见漏洞与防护实践

从GitHub安全案例解析常见漏洞与防护实践

1. 项目概述:从GitHub Trending看安全实战 最近在GitHub Trending上看到一个项目,叫 skills4/skills ,它因为一些安全漏洞案例被大家讨论。这其实是一个挺典型的场景:一个旨在展示或教授某种技能的仓库,本身却成了安…

2026/7/5 0:01:08阅读更多 →
MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

# MLT 2026启示:因果推理与概率建模驱动下一代LLM应用## 一、背景与挑战:从“黑箱预测”到“可信推理”2026年6月,第7届机器学习与趋势国际会议(MLT 2026)将在悉尼召开。会议议程中,“因果与可解释机器学习…

2026/7/5 0:01:08阅读更多 →
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时,通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中,是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

2026/7/5 0:01:08阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/5 1:30:27阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/5 3:48:10阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/5 3:48:09阅读更多 →