基于Service和Command模式的简单MVC实现

来源:互联网 发布:下载迅龙数据恢复 编辑:程序博客网 时间:2024/06/06 01:36

不久前在Jdon网站看到一篇很久的文章,说的是一个小型的Web项目中对MVC的简单实现,核心的观点就是:

 

1.只有一个Controllerservlet

2.一个Service接口

3.一些实现Service接口的类

 

其中Controller类是一个核心的请求分发器,用于对请求进行分配,Service是一个接口,其下有若干个实现类,每个Service实现类其实就是一个具体的业务层逻辑。我注意到其中关于控制的一段核心代码是这样的:

 

try {

//TODO:hashmap to reduce the generated instance?

 

Class serviceClass = Class.forName(serviceName);

Service service = (Service) serviceClass.newInstance();

service.execute(request, response, servletcontext);

 

} catch (ClassNotFoundException classnotfoundexception) {

     throw new ServletException(classnotfoundexception.getMessage());

} catch (IllegalAccessException illegalaccessexception) {

     throw new ServletException(illegalaccessexception.getMessage());

} catch (Exception exception) {

     throw new ServletException(exception.getMessage());

}

 

forward(request, response, targetName);

 

可以看到它是采用类的动态加载的方式来获取服务,服务的类型来自于请求的URL,也就是说每个请求后面都会付着一个ServiceName

 

个人觉得这是一个不错的MVC实现。实际上是采用了Command模式。

 

 

下面是我对这种方法的一个扩展:(目前仅限于想法,还没有具体的实现)

 

 

·DispatchServlet:

Servlet是核心控制Servlet,在容器启动时即被加载,所有的请求都首先被该Servlet所捕捉,根据该请求的类型转发给相应的子控制器。

 

 

·SubController

当服务比较多且多数的请求可以被归类成对某一类型的请求时,我们推荐使用SubController(注意:此处的SubController是一个总称,代表了对应于各个服务类型的请求,实际中可能有UserControllerJobController类等)。这样当中心Servlet将请求转交到SubController之后,可以由子控制器决定要调用服务层的那个方法。同时可以在此处根据业务需要,设置一些参数,用于控制或指定业务层的业务逻辑处理流程。

 

 

·Service:

ServiceeFrame中一个核心的接口,它代表了面向客户的一系列操作集合,如果从设计模式上看可以看成是Facade模式,屏蔽了用户和多个底层类的直接交互。Service接口有一个ServiceResult execute(Message message)方法,它接受一个Message对象作为服务的参数。并返回一个ServiceResult对象,告诉调用者服务的执行结果和具体内容。

 

   ·NonStatusService:

     无状态服务,代表了一次短期完成、不会被打断的服务。其下有一子类:

     ·HTTPService:

       HTTP服务类,代表了一次HTTP Call,通常是控制器将请求,上下文参数传给该服务,该服务在实现了业务逻辑后,将响应输出至页面

  

   ·StatusService:

  有状态服务,代表了一次长时间运行、可能会被随时中断的后台操作,例如从后台数据库中取出一批数据发送到客户端,该服务除了具备其父类的execute方法,还具备了一个表示服务当前状态的标志,以及启动、停止、执行服务的方法。

     ·MMSService   

   有状态服务的一个例子,该例子是用于从后台数据库中取出一批数据,然后采用多线程的方式向服务器发送数据由于发送量比较大,可能会被中途中断。所以系统需要记录该服务的起始时间、当前状态。

 

      

·ServiceResult:

ServiceResult代表了一次服务的执行结果,它具有两个常量:SUCCESSFAILED。分别代表了一次服务的成功执行和失败。除此之外它还拥有一个用于记录执行具体结果或返回值的HashMap对象:ResultDetail

 

 

·ServiceLocator

ServiceLocator是一个服务定位器,用于根据服务类的全称或者JNDI名称查找相应的服务类对象,这是一个接口。在其下有一个Service locate(String servieName)方法,用定位服务对象。

 

    ·ClassLoaderServiceLocator:使用Java的动态加载机制、反射机制创建服务对象

    ·JNDIServiceLocator:使用JNDI方式查找加载服务

 

   

·ServiceManager

ServiceManager是一个接口,它用于管理系统中存在的各个Service对象。由于Service对象多数采用动态加载或JNDI查询的方式产生,所以再性能上会比较慢,由于该类中包含了一个HashMap对象,所有生成的Service对象都会被缓存到其中,所以我们可以对运行时刻的Servcie对象具有完全的控制。

 

ServiceManager接口包含下列方法:

  ·register(String serviceId, Service service):注册一个服务

  ·get(String serviceId):获取一个Service对象

  ·remove(String serviceId):移除一个Service对象

  ·clear():清空所有的Service对象

 

ServiceManager有两个实现类,分别对应于无状态服务和有状态服务的管理

  ·NonStatuesServiceManager

    实现了ServiceManager接口的所有方法

  ·StautsServiceManager

    除了实现接口的方法之外,还具备了对服务状态的记录,服务的启动、停止的管理

    ·start(String serviceId):启动一个服务

    ·stop(String serviceId):停止一个服务

    ·getStatus(String serviceId):获取一个服务

 

 

·Message

Message类代表了一次服务执行中调用者向执行者传递的消息。它包含了以下几个元素:

   ·messageFrom:消息的来源

   ·messagTo:消息的接收者

   ·action:消息的目标动作

   ·paramters:消息的目标动作执行时所需的参数

 此外Message还具备以下方法:

   ·设置/获取消息的来源

   ·设置/获取消息的目的地

   ·设置/获取消息的目标动作

   ·设置/获取消息的目标动作所需参数

 Message对象的创建和传递通常发生在子控制器调用相应的业务逻辑之前

 

 

·AbstractFactory

AbstractFactory是一个抽象工厂类,它代表了一个能够根据用户需求而产生出不同类型对象的工厂,它具有一个抽象的方法

  ·public abstract Product getProduct(String productType):返回一个指定类型的产品

    AbstractFactory下可以有多个继承的子类,这些继承的子类都集中于某一类型构建,比如说DaoFactory

 

   ·DaoFactory

     DaoFactory类是继承了AbstracFactory类的子类,它的目标集中于DAO对象的构建,它返回的是一个实现了Product接口的Dao类实例

 

     

·Dao

Dao类是一个抽象类,它具备了对数据库操作的一系列基本元素,包括获取数据库连接、获取执行语句,迭代结果集等等。它有3个抽象的方法。分别是:

   ·public abstract int insert(Object object):插入一个对象

   ·public abstract int modify(Object object):修改一个对象

   ·public abstract int delete(Object object):删除一个对象

 

由于Dao类对象也属于工厂中生产出来的产品,所以这里我们让Dao类实现了Product接口。Dao类下面可以有多个继承的子类。不同的子类对于如何插入、更新、删除一个对象是不同的。

 

 

·Product

Product是一个虚拟的概念,它代表了一个从工厂中生产出来的产品。这个接口本身没有任何的方法

 

 

也就是说,每次Web层的请求的处理流程如下:

 

·Web请求

     |--->DispatchServlet                          

               |--->SubController

                         |--->Service

                                   |--->SubService(NonStatusService / StatusService)

                                             |--->DaoFactory

                                                       |--->Dao

                                                                 |--->SubDao

                                                                           |--Product

   Web页面<----------------------------------- Domain|                           

 

 

其中在SubController加载相应的Service时,会将相应的参数封装在Message对象中传递给Service对象。服务在执行后会返回一个

ServiceResult对象表示执行的结果情况。

 

Servcie的加载就像上面提到的可以采用Class.forName,也可以采用JNDI的方式。

 

附录:Jdon论坛参考文章地址:一个小的WEB项目中的实现方法讨论