MVC 多层架构1

多层架构是什么?

多层架构是开发人员在开发过程中面对复杂且易变的需求采起的一种以隔离控制为主的应对策略,关于多层架构的标准,我认为有一句话是比较有表明性的“每一层均可以单独部署”,最传统,最简单的就是从三层开始的:html

将整个项目自下而上的分为:数据持久(数据访问)层,逻辑(业务)层,UI(展示)层。前端

数据访问层:负责将数据持久化响应的数据存储设备上,如DataBase,Txt,Excel等。服务器

业务逻辑层:负责处理为知足软件需求而订制的一系列的逻辑与业务,如用户在前端下订单以后,整个业务流可能涉及到,获取用户信息,获取商品信息,获取购物车信息,验证商品可购买数量是否知足本次购买,针对用户身份产生不一样的优惠策略,同时会验证Cookie,Session等端产生数据的有效性,最终才会产生订单,而订单产生以后会涉及到仓储物流等一系列的Erp系统业务,全部的这一套都属于“下订单”这一需求的业务逻辑。架构

展现层:负责与用户交互的界面,良好的用户体验可能是使用在这里。并发

学习过Petshop的话,对于三层都不会陌生:框架

可是随着业务的复杂每一层都会有本身的进化,最终有了无数附加在三层之上的框架与开发思想。分布式

Mvc与MVP:

首先我一直认为这两种事属于展示层的,“展示层MCV”,“展示层MVP”。工具

而后咱们站在展示层的角度思考一下“Mvc”与“MVP”。学习

Mvc:分为model,Controller,View,相信你们对于他已经很熟悉了,在此再也不累述。ui

MVP:MVP有Model-Presenter-View三个层次

其实在楼主最开始接触Mvc的时候,就在想若是直接经过Controller与Model交互是否是显得有一些“不干净”,由于在楼主眼里“展示层的Controller”,作得最多的应该就是对于请求路由的不一样响应与调用,可是不少的例子会将一些数据验证,去糟的操做过程放在Controller中,显得不三不四。当MVP出现的时候,一切知足了楼主的幻想,P的过程就是知足了这一需求,P起到中介的做用,负责接收视图请求,再把结果映射到view上,P能够不对View作强引用,可经过IView适配多个view。固然我也会在这里作一些针对于终端数据的验证与过滤。

业务逻辑:

从描述上能够看的很清楚,整个自上而下的结构,最复杂,最可能失控的就是业务逻辑层,由于其中包含着许多的不可控因素,每一个行业领域的需求都有可能包含自身的领域知识。因而在以后的多层架构发展构成当中,更多的变化与智慧是体如今这里。

领域驱动:限于本人才学不能在这里分享太多,以防误导你们,想了解更多可参考园子里的其余大牛,其实没有3,5年相关经验是很难理解的,我的感受若是你不理解的话也不会对你有什么影响,由于领域驱动是创建在良好的面相对象分析,边界划分基础之上的,在学习的过程中已经能帮助你去学习到足够多的知识了,最终到不到山巅其实已经无所谓了。

简单的说,这个思想最重要的是以业务领域为核心进行发散,指望在变动程序的其余部分,不会影响到领域模型,也就是那句话为了“复杂的系统应用程序中业务规则行为方式(就是“领域逻辑”)是会常常变化的,咱们要去拥抱这种变化”。结构图:

CQRS:是指命令查询职责的分离,是一个小的模式形态,该模式的关键在于:“一个方法要么是用来改变某个对象的状态的,要么就是返回一个结果,这二者不会同时并存”。将整个系统分拆为两个部分:

  • Commands(命令) - 改变某一个对象或整个系统的状态(有时也叫作modifiers或者mutators)。
  • Queries(查询) - 返回值而且不会改变对象的状态。

架构图:

无论DDD也好,CQRS也好,其实这两种都不会100%适合全部的项目架构的,这就须要架构师结合项目自己特色及需求有所选择,可是其中的思想咱们能够运用在项目的任何地方。

基于消息的分布式:

其实无论使用怎样的架构,加入怎样的架构思想(soa),核心或者是开发者最想达到的就是层次,系统之间的解耦,复杂的东西没人会喜欢。

随着系统的发展,咱们的程序会涉及到多台服务器,多种终端,同时为了解耦咱们引入了基于消息的分布式架构。

首先,因此系统的通讯基于消息,逻辑联系不会涉及到具体的业务实现,同时消息的传递更加的廉价可适配多种终端。

其次,因为所用逻辑只是基于消息实现,迭代的成本也会相对于其余耦合项目更快更方便。

展现层:

随之Web2.0的到来单一页面展现的信息也更加的丰富,Ajax,js的流行也使得Ui端的操做也越发变重,因而你们有指望以一种工程的思想去拥抱这种变化,因而MVVM,js的Mvc框架陆续出现。同时随着移动互联网的兴起,不一样终端对于系统的对接也很是重要,因而咱们考虑在Ui与Logic之间引入Application或Service层应对不一样终端配置。

如:咱们在Client Presenter Layer 上加入WCF适配多种终端提交的订单,都是创建在消息基础之上的,楼主以前作电商系统是针对于来自淘宝,天猫,亚马逊订单时,为避免出现对库中订单并发,产生“超买”状况,采用了在上层Ui与logic层之间引入了OrderChannel层,将不一样终端订单进行排队的解决方案。

以上是架设一个可以适配不一样需求的架构过程,可是真正的真理是须要你们在实践中,错误中汲取的。

下面是楼主简单的小分层架构,不妥,不足之处但愿你们指导斧正。

层次划分:

为了实现单独部署,层次解耦因此层次之间是基于接口实现的。

DataAccess层引入仓储实现统一DTO操做,实现基于Ef:

IRepository:

  1. public interface IRepository<T> where T:class 
  2.     {  
  3.         IEnumerable<T> FindAll(Expression<Func<T,bool>> exp);  
  4.         void Add(T entity);  
  5.         void Delete(T entity);  
  6.         void Submit();  
  7.     } 

引入RepositoryBase实现接口定义:

  1. public class RepositoryBase<T>:IRepository<T> where T:class 
  2.     {  
  3.         DbContext context;  
  4.         public RepositoryBase(DbContext _context)  
  5.         {  
  6.             context = _context;  
  7.         }  
  8.  
  9.         public RepositoryBase() {  
  10.             this.context = new TestDBEntities();  
  11.         }  
  12.  
  13.         public IEnumerable<T> FindAll(Expression<Func<T, bool>> exp)  
  14.         {  
  15.             return context.Set<T>().Where(exp);  
  16.         }  
  17.  
  18.         public void Add(T entity)  
  19.         {  
  20.             context.Set<T>().Add(entity);  
  21.         }  
  22.  
  23.         public void Delete(T entity)  
  24.         {  
  25.             context.Set<T>().Remove(entity);  
  26.         }  
  27.  
  28.         public void Submit()  
  29.         {  
  30.             context.SaveChanges();  
  31.         }  
  32.     } 

这对于单一的某个仓储咱们单独引入其自身的仓储接口:

  1. public interface IUserRepository:IRepository<UserTest>  
  2. {  
  3.     IList<UserTest> GetAllById(int id);  
  4.  
  5.     bool CheckUserExist(UserTest u);  

特定仓储实现:

  1. public class UserRepository : RepositoryBase<UserTest>,IUserRepository  
  2.     {  
  3.         public IList<UserTest> GetAllById(int id)  
  4.         {  
  5.             using (TestDBEntities entities=new TestDBEntities())  
  6.             {  
  7.                 var users = from u in entities.UserTests  
  8.                             where u.ID == id  
  9.                             select u;  
  10.                 return users.ToList();  
  11.             }  
  12.         }  
  13.  
  14.         public bool CheckUserExist(UserTest u)  
  15.         {  
  16.             using (TestDBEntities entities = new TestDBEntities())  
  17.             {  
  18.                 List<UserTest> users = entities.UserTests.Where(ut => ut.UserName == u.UserName && ut.UserPassword==u.UserPassword).ToList<UserTest>();  
  19.                 return users.Count==0 ? false : true;  
  20.             }  
  21.         }  
  22.     } 

在Service层一样创建相关接口适配特种服务:

IUserCore:

  1. public interface IUserCore  
  2.     {  
  3.         CommandStatueEnum UserLogin(IModel model);  
  4.         CommandStatueEnum UserRegister(IModel model);  
  5.  
  6.         List<UserTest> GetUsers(Expression<Func<UserTest, bool>> expr);  
  7.     } 

UserCore:

  1. public class UserCore : IUserCore  
  2.     {  
  3.         #region Structure  
  4.         IUserRepository _repository;  
  5.         public UserCore(IUserRepository repository) {  
  6.             this._repository = repository;  
  7.         }  
  8.         #endregion  
  9.  
  10.         public CommandStatueEnum UserLogin(IModel model)  
  11.         {  
  12.             try 
  13.             {  
  14.                 UserLogin u = model as UserLogin;  
  15.                 UserTest uTest = new UserTest();  
  16.                 uTest.UserName = u.UserName;  
  17.                 uTest.UserPassword = u.Password;  
  18.  
  19.                 if (_repository.CheckUserExist(uTest))  
  20.                 {  
  21.                     return CommandStatueEnum.Succeed;  
  22.                 }  
  23.                 else 
  24.                 {  
  25.                     return CommandStatueEnum.Fail;  
  26.                 }  
  27.             }  
  28.             catch (Exception ex) {  
  29.                 throw ex;  
  30.             }  
  31.         }  
  32.  
  33.         public CommandStatueEnum UserRegister(IModel model)  
  34.         {  
  35.             try 
  36.             {  
  37.                 UserLogin u = model as UserLogin;  
  38.                 UserTest uTest = new UserTest() { UserName=u.UserName, UserPassword=u.Password};  
  39.                 _repository.Add(uTest);  
  40.                 _repository.Submit();  
  41.                 return CommandStatueEnum.Succeed;  
  42.             }  
  43.             catch (Exception ex)  
  44.             {  
  45.                 throw ex;  
  46.             }  
  47.         }  
  48.  
  49.  
  50.         public List<UserTest> GetUsers(System.Linq.Expressions.Expression<Func<UserTest, bool>> expr=null)  
  51.         {  
  52.            return _repository.FindAll(expr).ToList<UserTest>();  
  53.         }  
  54.     } 

Controller:

  1. public class AccountController : Controller  
  2.     {  
  3.         IUserCore userCore;  
  4.         public AccountController(IUserCore _userCore)  
  5.         {  
  6.             this.userCore = _userCore;  
  7.         }  
  8.  
  9.         //  
  10.         // GET: /Account/  
  11.  
  12.         #region view  
  13.         public ActionResult Home()  
  14.         {  
  15.             ViewBag.Users = userCore.GetUsers(u=>u.IsUse==1);  
  16.             return View();  
  17.         }  
  18.  
  19.         public ActionResult Login()  
  20.         {  
  21.             return View();  
  22.         }  
  23.  
  24.         public ActionResult Register()  
  25.         {  
  26.             return View();  
  27.         }  
  28.         #endregion  
  29.  
  30.         #region Post  
  31.         [HttpPost]  
  32.         public ActionResult Login(UserLogin account)  
  33.         {  
  34.             try 
  35.             {  
  36.                 if (userCore.UserLogin(account) == CommandStatueEnum.Succeed)  
  37.                 {  
  38.                     return RedirectToAction("Home");  
  39.                 }  
  40.                 else 
  41.                 {  
  42.                     return View();  
  43.                 }  
  44.             }  
  45.             catch (Exception ex)  
  46.             {  
  47.                 ExceptionModel.IsExcept = true;  
  48.                 ExceptionModel.Exception = ex.ToString();  
  49.                 ExceptionModel.CreateTime = DateTime.Now;  
  50.                 return View();  
  51.             }  
  52.         }  
  53.  
  54.         [HttpPost]  
  55.         public ActionResult Register(UserLogin account)  
  56.         {  
  57.             try 
  58.             {  
  59.                 if (userCore.UserRegister(account) == CommandStatueEnum.Succeed)  
  60.                 {  
  61.                     return RedirectToAction("Home");  
  62.                 }  
  63.                 else 
  64.                 {  
  65.                     return View();  
  66.                 }  
  67.             }  
  68.             catch (Exception ex)  
  69.             {  
  70.                 ExceptionModel.IsExcept = true;  
  71.                 ExceptionModel.Exception = ex.ToString();  
  72.                 ExceptionModel.CreateTime = DateTime.Now;  
  73.                 return View();  
  74.             }  
  75.         }  
  76.         #endregion  
  77.     } 

对于接口之间咱们经过引入IOC工具解耦:

  1. public class MvcApplication : System.Web.HttpApplication  
  2.     {  
  3.         protected void Application_Start()  
  4.         {  
  5.             AreaRegistration.RegisterAllAreas();  
  6.  
  7.             WebApiConfig.Register(GlobalConfiguration.Configuration);  
  8.             FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);  
  9.             RouteConfig.RegisterRoutes(RouteTable.Routes);  
  10.             BundleConfig.RegisterBundles(BundleTable.Bundles);  
  11.             AuthConfig.RegisterAuth();  
  12.  
  13.             #region IOC  
  14.             var builder = new ContainerBuilder();  
  15.             SetupResolveRules(builder);  
  16.             builder.RegisterControllers(Assembly.GetExecutingAssembly());  
  17.             var container = builder.Build();  
  18.             DependencyResolver.SetResolver(new AutofacDependencyResolver(container));  
  19.             #endregion  
  20.         }  
  21.  
  22.         private void SetupResolveRules(ContainerBuilder builder)  
  23.         {  
  24.             //Components are wired to services using the As() methods on ContainerBuilder  
  25.             builder.RegisterType<UserCore>().As<IUserCore>();  
  26.             builder.RegisterType<UserRepository>().As<IUserRepository>();  
  27.         }  
  28.  
  29.     } 

其余基础类库咱们会结合具体需求进行定制,上面例子多有不妥之处只起演示之用。

综上所述,本篇只起抛砖引玉之用,还请大牛拍砖指导。

原文连接:http://www.cnblogs.com/xiguain/p/3636022.html

相关文章
相关标签/搜索