MVC基础——市场管理系统(三)Clean Architecture


文章目录

  • 项目地址
  • 五、Clean Architecture
    • 5.1 user cage driven
      • 5.1.1创建CoreBusiness
    • 5.2 创建UseCases
      • 5.2.1 创建CategoriesUseCases
        • 1. 创建`VeiwCategoriesUseCase`获取所有Cagegory
      • 5.2.2. 实现ICategoryRepository接口
        • 3. 实现获取所有Category的方法
        • 4. 实现获取一个Cagegory的方法
        • 5. 实现编辑Category的方法
        • 6. 实现获取删除Category的方法
      • 5.2.3 创建ProductsUseCases
        • 1. 创建一个AddProductUseCase
        • 2. 使用快捷键生成IProductRepository接口
        • 3. 通过快捷键生成接口对应的AddProduct方法
        • 4. 通过同样的方式,将剩下的几个UseCase完成
        • 5. 通过快捷键将UseCase 提取成为接口
          • 6. Product的内存Plugin的完善
    • 5.3 创建Plugins
      • 5.3.1 实现一个内存存储的plugin
    • 5.4 在Controllers里使用IOC
      • 5.4.1 将项目所用到的所有服务,注册到容器中
      • 5.4.2 添加程序集的引用给UI层
      • 5.4.3 从依赖注入容器里获取需要的服务
      • 5.4.4 修改之前代码通过使用接口的方法
        • 1. 在Validataion的服务里直接实例化IProductsRepository
        • 2. 创建一个ISellProductUseCase
    • 5.5 所有容器注册完毕,结构展示
      • 5.5.1 Plugins/CoreBusiness
      • 5.5.2 UseCases类库
        • 1. UseCases里的各个组成
        • 2. 每个Usecase里的方法和DataStorePluginInterface的关系


项目地址

  • 教程作者:
  • 教程地址:
  • 代码仓库地址:
  • 所用到的框架和插件:
dbt 
airflow

五、Clean Architecture

  1. usecase driven
  2. plugin based

5.1 user cage driven

5.1.1创建CoreBusiness

业务实体存放的类

  1. 创建一个class library,CoreBusiness
  2. Models文件夹下的Categories.csProducts.cs以及Transactions.cs三个实体类,移动到CoreBusiness类库里,并修改他们的namespace

5.2 创建UseCases

  • 创建UseCases类库

5.2.1 创建CategoriesUseCases

  • 从功能出发,如果我们需要一个处理Categories相关的业务,需要对Categories数据表有哪些操作
  1. 查询出所有的Categories, ViewCategoriesUseCase.cs
  2. 查询单个Category的信息,ViewSelectedCategoryUseCase.cs
  3. 添加单个Category,AddCategoryUseCase.cs
  4. 编辑单个Category,EditCategoryUseCase.cs
  5. 删除单个Category,DeleteCategoryUseCase.cs
1. 创建VeiwCategoriesUseCase获取所有Cagegory
  1. 在UseCases类库里,创建文件夹CategoriesUseCases文件夹
  2. 在该文件夹下添加ViewCategoriesUseCase.cs
  3. ViewCategoriesUseCase.cs 只有一个公共的方法对外使用,因为他的功能显示Category的列表
  4. 添加对CoreBusiness的引用
  5. 创建一个返回所有Category的方法Excute()
public IEnumerable<Category> Excute()
{
}
  1. 使用构造方法,注入一个ICategoryRepository,这里这个接口还没有实现,只是我们知道我们需要用到这个接口提供的方法来获取我们想要的数据,这就是usecase driven的核心
namespace UseCases.CategoriesUseCases
{public class ViewCategoriesUseCase{private readonly ICategoryRepository _categoryRepository;public ViewCategoriesUseCase(ICategoryRepository categoryRepository){this._categoryRepository = categoryRepository;}public IEnumerable<Category> Excute(){//需要用到这个接口给我们提供的GetCategories方法获取数据return _categoryRepository.GetCategories();}}
}
  1. 至此,就完成了一个简单的Use Case Driven,在UseCases层,我们关心,接口哪里来,在哪里实现,只关心我需要这个接口以及接口能解决问题的方法,只是接口的使用者;

5.2.2. 实现ICategoryRepository接口

定义了与 Category 实体相关的操作,所有关于Category的操作都在这个接口上,供给plugins使用

在这里插入图片描述

1 . 在UseCases里创建文件夹DataStorePluginInterfaces
2. 创建ICategoryRepository.cs

using CoreBusiness;namespace UseCases.DataStorePluginInterfaces
{public interface ICategoryRepository{}
}
  1. 然后通过CategoriesUseCases里创建的方法,来逆向实现接口

在这里插入图片描述

3. 实现获取所有Category的方法
  • ViewCategoriesUseCase.cs里实现GetCategories()方法,该类只负责获取所有的Category列表,单一职责
using CoreBusiness;
using UseCases.DataStorePluginInterfaces;namespace UseCases.CategoriesUseCases
{public class ViewCategoriesUseCase{private readonly ICategoryRepository _categoryRepository;public ViewCategoriesUseCase(ICategoryRepository categoryRepository){this._categoryRepository = categoryRepository;}public IEnumerable<Category> Excute(){return _categoryRepository.GetCategories();}}
}
4. 实现获取一个Cagegory的方法
  • 创建ViewSelectedCategoryUseCase.cs,该类只负责获取一个Cagegory

namespace UseCases.CategoriesUseCases
{public class ViewSelectedCategoryUseCase{private readonly ICategoryRepository _categoryRepository;public ViewSelectedCategoryUseCase(ICategoryRepository categoryRepository){this._categoryRepository = categoryRepository;}public Category Excute(int categoryId){return _categoryRepository.GetCategoryById(categoryId);}}
}
5. 实现编辑Category的方法
  • 创建EditCategoryUseCase.cs,该类只负责传递一个categoryId和cateogry类,编辑Category
namespace UseCases.CategoriesUseCases
{public class EditCategoryUseCase{private readonly ICategoryRepository _categoryRepository;public EditCategoryUseCase(ICategoryRepository categoryRepository){this._categoryRepository = categoryRepository;}public void Excute(int categoryId,Category catogory){_categoryRepository.UpdateCategory(categoryId, catogory);}}
}
6. 实现获取删除Category的方法
  • 创建EditCategoryUseCase.cs,该类只负责通过id删除category
namespace UseCases.CategoriesUseCases
{public class DeleteCategoryUseCase{private readonly ICategoryRepository _categoryRepository;public DeleteCategoryUseCase(ICategoryRepository categoryRepository){this._categoryRepository = categoryRepository;}public void Excute(int categoryId){_categoryRepository.DeleteCategoryById(categoryId);}}
}

5.2.3 创建ProductsUseCases

所有的UseCases只有一个公共的方法Excute()的好处:

  1. 单一职责,只要是usecase就只有Excute的方法
  2. 统一入口点都是Excute(),这样以后使用泛型或者反射都易于调用
  • 从功能出发,如果我们需要一个处理products相关的业务,需要对products数据表有哪些操作
  1. 查询出所有的products, ViewProductsUseCase.cs
  2. 查询单个product的信息,ViewSelectedProductUseCase.cs
  3. 添加单个product,AddProductUseCase.cs
  4. 编辑单个product,EditProductUseCase.cs
  5. 删除单个product,DeleteProductUseCase.cs
  • 可以看出来以上都是基础的增删改查,和CategoriesUseCases 基本一样,下面是products自己独有的方法
1. 创建一个AddProductUseCase
  • 这里,我们先不用考虑程序里有什么接口,有什么功能,我们只需要写
    1. 创建一个Excute函数,在所有的UseCase的公共出口
    2. 函数里面里根据功能,这里是添加一个Products,所以直接调用 _productRepository.AddProduct(product);
    3. 通过构造函数从容器中拿我需要repository

在这里插入图片描述

2. 使用快捷键生成IProductRepository接口
  • 使用快捷键 生成接口,将会自动在原目录下生成一个IProductRepository.cs的文件
    在这里插入图片描述
  • IProductRepository.cs
namespace UseCases.ProductsUseCases
{public interface IProductRepository{}
}
  • 将自动该文件移动到DataStorePluginInterfaces文件夹下
3. 通过快捷键生成接口对应的AddProduct方法
  • 继续使用快捷键,往接口里添加AddProduct方法
    在这里插入图片描述
  • 此时,在IProductRepository接口里,我们的方法已经添加成功
using CoreBusiness;namespace UseCases.ProductsUseCases
{public interface IProductRepository{void AddProduct(Product product);}
}
4. 通过同样的方式,将剩下的几个UseCase完成
5. 通过快捷键将UseCase 提取成为接口

不要直接使用具体实现,而是通过接口使用UseCase

  • 使用快捷件, 将所有的UseCases提成接口

在这里插入图片描述

  • 会在同级目录下生成一个IAddProductUseCase.cs文件
using CoreBusiness;namespace UseCases.ProductsUseCases
{public interface IAddProductUseCase{void Execute(Product product);}
}
  • 并且自动,添加了该接口
    在这里插入图片描述
  • 创建interfaces文件夹,在UseCases类库内,将所有关于具体UseCases的用例接口放入

在这里插入图片描述

6. Product的内存Plugin的完善

在这里插入图片描述

  • 需要注意的是: Product商品的一些操作,需要和Category类进行交互,这和Category的plugin的区别;

在这里插入图片描述

5.3 创建Plugins

Plugins就是真正实现ICategoryRepository的地方

5.3.1 实现一个内存存储的plugin

  • 实现内存存储

1.在项目的根目录下创建一个Plugins文件夹,除了在vs里创建,还需要到项目的Folder里创建,因为vs创建的文件夹只是一个视图文件夹,真正的文件夹要在folder里创建

在这里插入图片描述
2. 创建一个Plugins.DateStore.InMemory类库,并在类库里创建CategoriesInMemoryRepository.cs,该类库实现了ICategoryRepository的所有功能

 public class CategoriesInMemoryRepository : ICategoryRepository
  1. 将之前我们使用的内存存储和查询的方法,放到该类库内
    在这里插入图片描述
  2. 由于方法的名称一样,这里直接使用即可
    在这里插入图片描述

5.4 在Controllers里使用IOC

  • 此时,就体现出了,创建具体UseCases的实例接口的好处,我们通过依赖注入是通过接口实例化,而不是直接通过实例,结耦

5.4.1 将项目所用到的所有服务,注册到容器中

  • 在程序入口,将服务注册进来

在这里插入图片描述

5.4.2 添加程序集的引用给UI层

  • 因为UI层,是表现层,所以他需要将所有相关的类库,都引入进来

在这里插入图片描述

5.4.3 从依赖注入容器里获取需要的服务

  1. 通过构造函数从容器里,直接获取需要的服务
  2. 直接通过注册服务的名字,就可以知道服务的功能,并且执行统一的Excute()方法
    在这里插入图片描述

5.4.4 修改之前代码通过使用接口的方法

1. 在Validataion的服务里直接实例化IProductsRepository
  • 由于中间件的生命周期不一样, 在这里我们直接使用接口在Validation的context里直接获取

在这里插入图片描述

2. 创建一个ISellProductUseCase
  • 没创建之前,进行数据的操作直接在Controller里,这是不应该发生的,现在创建了该接口之后,只需要传递相应的数据即可

在这里插入图片描述

5.5 所有容器注册完毕,结构展示

5.5.1 Plugins/CoreBusiness

  • Plugin里是UseCases/DataStorePluginInterfaces里接口的实现,这里对接的各个数据库
  • CoreBuniess里只存放实例类,真实的数据库的实体

在这里插入图片描述

5.5.2 UseCases类库

1. UseCases里的各个组成
  1. interfaces里所有接口都是各个usecase提取出的,作用就是用于注册IOC服务,可以在controller里用;
  2. DataStorePluginInterfaces,各个数据库需要继承的库
    在这里插入图片描述
2. 每个Usecase里的方法和DataStorePluginInterface的关系

真正实现usecase的方法实际上是AddCategory方法,该方法是提取到ICategoryRepository里的实际方法

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/62851.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

手机上和电脑上都能观看的翻页电子书是如何制作的?

想知道手机上和电脑上都能观看的翻页电子书是都是如何制作的&#xff1f; 想知道这样的电子书是怎样呈现出来的&#xff1f; 那收藏这篇文章&#xff0c;我来跟大家说说该如何实现。 操作方法 一、登录FLBOOK 二、开始制作&#xff0c;有多种创建方式&#xff0c;分别是&…

Java 实现给pdf文件指定位置盖章功能

Java 实现给pdf文件指定位置盖章功能 开发中遇到一个需求, 需要给用户上传的的pdf文件, 指定位置上盖公章的功能, 经过调研和对比, 最终确定实现思路. 这里是使用pdf文件中的关键字进行章子的定位, 之所以这样考虑是因为如果直接写死坐标的话, 可能会出现因pdf大小, 缩放, 盖章…

ASP.NET Core API + MySql

环境 数据库&#xff1a; mysql8.0 后端&#xff1a; vs2022 ASP.NET Core API .net 8 前端&#xff1a; Hbuilderx bootstrap 5.3.0 jquery v3.7.1 bootstrap-table 1.23.5 创建项目 添加资源包 AutoMapper Microsoft.EntityFrameworkCore.Tools 8.0.0 Pomelo.EntityFramew…

Bananna Pi开源社区联合矽昌通信打造开源的低成本Wifi5路由器

香蕉派 BPI-Wifi5 路由器采用矽昌SF19A2890S2芯片方案设计。它是一款高性能无线路由器&#xff0c;适用于小微企业、家庭和其他网络环境。Banana Pi开源社区提供整体解决方案。所有代码开源&#xff0c;用户可以在上面自由开发自己的应用。 Banana Pi wifi5 路由器github代码: …

item2 for macos

安装Item2 brew install iterm2 查看终端类型 cat /etc/shells Mac OS X 10.15 已经将默认的shell从Bash换成了zsh&#xff0c;所以不用安装&#xff0c;10.15以前的可以使用下面的命令进行安装 brew install zsh 安装Oh My ZSH # curl sh -c "$(curl -fsSL https://ra…

Pytest-Bdd-Playwright 系列教程(14):Docstring 参数

Pytest-Bdd-Playwright 系列教程&#xff08;14&#xff09;&#xff1a;Docstring 参数 前言一、什么是docstring?二、基本语法三、主要特点四、实际例子五、注意事项六、使用建议总结 前言 在自动化测试的过程中&#xff0c;我们经常需要处理复杂的测试数据或需要输入多行文…

手机租赁系统开发指南一站式服务流程解析

内容概要 手机租赁系统的开发是一个复杂但有趣的过程&#xff0c;像搭建乐高一样&#xff0c;只要找到合适的模块&#xff0c;就能打造出一个宾至如归的租赁平台。在这部分&#xff0c;我们将对开发流程的整体结构进行简要概述&#xff0c;并指出每个环节的重要性。 首先&…

OpenAI 正式赋予 ChatGPT 通过视频实时与用户互动的能力

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

EasyExcel设置表头上面的那种大标题(前端传递来的大标题)

1、首先得先引用easyExcel的版本依赖&#xff0c;我那 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.6</version> </dependency> 2、然后得弄直接的实体类&#xff0c;&…

纯血鸿蒙崛起,原生Android挑战?两大操作系统巅峰对决,智能设备未来谁主沉浮?

鸿蒙HarmonyOS和原生Android系统虽然在一些方面相似&#xff0c;但在架构、设计理念、API、开发工具等方面存在一些差异。鸿蒙系统的目标是跨设备、分布式的操作系统&#xff0c;强调多设备协同和资源共享&#xff0c;而Android则主要集中在智能手机和移动设备领域。 下面将从…

计算机网络:传输层、应用层、网络安全、视频/音频/无线网络、下一代因特网

目录 &#xff08;五&#xff09;传输层 1&#xff0e;传输层寻址与端口 2&#xff0e;无连接服务与面向连接服务 3. 传输连接的建立与释放 4. UDP 的优点 5. UDP 和 TCP 报文段报头格式 6. TCP 的流量控制 7&#xff0e;TCP 的拥塞控制 8. TCP 传送连接的管理 &#…

【前端开发】HTML+CSS网页,可以拿来当作业(免费开源)

HTML代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content_lizhongyu"widthdevice-width, initial-scale1.0"><title>小兔鲜儿-新鲜、惠民、快捷<…

CV(4)--边缘提取和相机模型

前言 仅记录学习过程&#xff0c;有问题欢迎讨论 边缘提取&#xff08;涉及语义分割&#xff09;&#xff1a; 图象的边缘是指图象局部区域亮度变化显著的部分,也有正负之分&#xff0c;暗到亮为正 求边缘的幅度&#xff1a;sobel&#xff0c;Canny算子 图像分高频分量和低…

智能技术引领未来:自动图像标注的创新应用与发展

&#x1f351;个人主页&#xff1a;Jupiter. &#x1f680; 所属专栏&#xff1a;传知代码 欢迎大家点赞收藏评论&#x1f60a; 目录 概述算法原理核心逻辑效果演示使用方式参考文献 参考文献&#xff1a;需要本文的详细复现过程的项目源码、数据和预训练好的模型可从该地址处获…

C语言-排序

常见的排序算法分为以下四种&#xff0c;插入排序&#xff0c;选择排序&#xff0c;交换排序&#xff0c;归并排序。 一、插入排序 (一)直接插入排序 直接插入排序&#xff0c;将一段数组看做被分成已排序序列和未排序序列&#xff0c;排序过程是从未排序序列的元素开始&…

【Java笔记】LinkedList 底层结构

一、LinkedList 的全面说明 LinkedList底层实现了双向链表和双端队列特点可以添加任意元素(元素可以重复)&#xff0c;包括null线程不安全&#xff0c;没有实现同步 二、LinkedList 的底层操作机制 三、LinkedList的增删改查案例 public class LinkedListCRUD { public stati…

网管平台(基础篇):路由器的介绍与管理

路由器简介 路由器&#xff08;Router&#xff09;是一种计算机网络设备&#xff0c;它的主要作用是将数据通过打包&#xff0c;并按照一定的路径选择算法&#xff0c;将网络传送至目的地。路由器能够连接两个或更多个网络&#xff0c;并根据信道的情况自动选择和设定路由&…

排序算法(2):选择排序

问题 排序 [30, 24, 5, 58, 18, 36, 12, 42, 39] 选择排序 选择排序每次从待排序序列中选出最小&#xff08;或最大&#xff09;的元素&#xff0c;将其放到序列的起始位置&#xff0c;然后&#xff0c;再从剩余未排序元素中继续寻找最小&#xff08;或最大&#xff09;元素…

Tongweb8命令行使用收集(by lqw)

文章目录 声明对应版本修改thanos用户密码部署应用到默认实例节点相关操作新增节点(一般一个服务器ip只能装一个节点)启动节点(需确认节点没有运行)停止节点删除节点节点新增应用节点查看应用节点启动应用节点停止应用节点卸载应用(谨慎操作,卸载后应用就没有了,建议备份后…

Artec Leo3D扫描仪在重型机械设备定制中的应用【沪敖3D】

挑战&#xff1a;一家加拿大制造商需要有效的方法&#xff0c;为富于变化且难度较高的逆向工程&#xff0c;快速、安全、准确地完成重型机械几何采集。 解决方案&#xff1a;Artec Leo, Artec Studio, Geomagic for SOLIDWORKS 效果&#xff1a;Artec Leo三维扫描代替过去的手动…