<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>绿色记忆 &#187; 架构模式</title>
	<atom:link href="https://blog.gmem.cc/tag/%e6%9e%b6%e6%9e%84%e6%a8%a1%e5%bc%8f/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.gmem.cc</link>
	<description></description>
	<lastBuildDate>Fri, 03 Apr 2026 04:13:36 +0000</lastBuildDate>
	<language>en-US</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.9.14</generator>
	<item>
		<title>反应器模式</title>
		<link>https://blog.gmem.cc/reactor-pattern</link>
		<comments>https://blog.gmem.cc/reactor-pattern#comments</comments>
		<pubDate>Sat, 21 Mar 2015 08:48:28 +0000</pubDate>
		<dc:creator><![CDATA[Alex]]></dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[架构模式]]></category>
		<category><![CDATA[设计模式]]></category>

		<guid isPermaLink="false">https://blog.gmem.cc/?p=25349</guid>
		<description><![CDATA[<p>模式定义 反应器模式（Reactor pattern）是一种事件处理模式，用于处理从一个或多个输入并发的发送给单个服务处理器（service handler）的请求。服务处理器对请求进行多路分用（demultiplexes） —— 解析并分发（dispatcher）给请求处理器（service handler）。 反应器模式通常是单线程的，但是它可以在多线程系统中运行。 模式结构和说明 角色 资源 能够为系统提供输入，或者消费系统的输出。 同步事件多路分离器 即Synchronous Event Demultiplexer，负责运行事件循环， 在所有资源上阻塞。当可以在资源上执行异步操作时，此分离器将资源转给分发器（dispatcher）。 分发器 能够注册、解除注册请求处理器，分发来自Demultiplexer的资源给相应的请求处理器。 请求处理器 处理特定类型的资源。 应用举例 <a class="read-more" href="https://blog.gmem.cc/reactor-pattern">[...]</a></p>
<p>The post <a rel="nofollow" href="https://blog.gmem.cc/reactor-pattern">反应器模式</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></description>
				<content:encoded><![CDATA[<div class="wri_content_clear_both"><div class="blog_h1"><span class="graybg">模式定义</span></div>
<p>反应器模式（Reactor pattern）是一种<span style="background-color: #c0c0c0;">事件处理模式</span>，用于处理从一个或多个输入<span style="background-color: #c0c0c0;">并发的发送</span>给单个服务处理器（service handler）的请求。服务处理器对请求进行多路分用（demultiplexes） —— 解析并分发（dispatcher）给请求处理器（service handler）。</p>
<p>反应器模式通常是单线程的，但是它可以在多线程系统中运行。</p>
<div class="blog_h1"><span class="graybg">模式结构和说明</span></div>
<div class="blog_h2"><span class="graybg">角色</span></div>
<div class="blog_h3"><span class="graybg">资源</span></div>
<p>能够为系统提供输入，或者消费系统的输出。</p>
<div class="blog_h3"><span class="graybg">同步事件多路分离器</span></div>
<p>即Synchronous Event Demultiplexer，<span style="background-color: rgb(192, 192, 192);">负责运行事件循环</span>， 在所有资源上阻塞。当<span style="background-color: rgb(192, 192, 192);">可以在资源上执行异步操作时</span>，此分离器将资源转给分发器（dispatcher）。</p>
<div class="blog_h3"><span class="graybg">分发器</span></div>
<p>能够注册、解除注册请求处理器，分发来自Demultiplexer的资源给相应的请求处理器。</p>
<div class="blog_h3"><span class="graybg">请求处理器</span></div>
<p>处理特定类型的资源。</p>
<div class="blog_h1"><span class="graybg">应用举例</span></div>
<div class="blog_h2"><span class="graybg">libevent</span></div>
<p>libevent是一个事件驱动编程库，可以在文件描述符上发生特定事件、超时后，执行相应的回调函数。回调函数还可以由信号、定时器触发。</p>
</div><p>The post <a rel="nofollow" href="https://blog.gmem.cc/reactor-pattern">反应器模式</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.gmem.cc/reactor-pattern/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MVC模式</title>
		<link>https://blog.gmem.cc/mvc-pattern</link>
		<comments>https://blog.gmem.cc/mvc-pattern#comments</comments>
		<pubDate>Thu, 20 Mar 2008 01:30:42 +0000</pubDate>
		<dc:creator><![CDATA[Alex]]></dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[架构模式]]></category>

		<guid isPermaLink="false">http://blog.gmem.cc/?p=7861</guid>
		<description><![CDATA[<p>模式说明 经典的MVC模式 MVC，即模型-视图-控制器，是一种用于用户界面设计/展示层的架构模式，起初出现在Smalltalk。MVC模式的核心是利用控制器作为中介，将视图和模型解耦。 MVC模式中三者的职责分工明确： 模型（Model）：持有所有的数据、状态和程序逻辑，模型不会感知到视图和控制器（下层组件不依赖于上层）。模型提供了操作和检索状态的接口，并且将状态改变信息推送给观察者（视图），在某些设计中，视图需要的数据被一同推送 视图（View）：用来呈现模型，视图通常直接从模型中获取它需要显示的状态和数据 控制器（Controller）：负责获取用户输入，并解读其对于模型的意义。控制器也可能直接要求视图做出改变。控制器不应当包含业务逻辑 注意和传统的模型含义不同，MVC中的模型不仅仅是指数据对象。以播放器为例，播放状态、当前歌曲、播放行为等都属于模型的组成部分。 三者的调用关系图如下： 上图虽然有箭头从Model指向View，但是这是一种松耦合的、基于观察者模式的通知方式。此外，某些设计中把Controller也作为Model的观察者，图中没有标出。 一般MVC中会用到三种设计模式： 观察者模式：Model作为事件源，View、Controller作为监听器 策略模式：对于View来说，Controller是具体策略，如果需要改变行为，可以更换一个Controller 组合模式：View中的GUI控件一般都呈现出树状组合关系 MVC2 经典的MVC模式适用于单机桌面程序的开发，由于Model、View运行在统一进程中，因而互相之间基于函数调用的通信很方便。在常见的Web应用场景中，Model是无法通知到View的，因为： 在使用服务器端脚本（PHP、JSP、ASP等）作为视图组件的情况下，这些视图都是一次性生成的过程，结果是HTML代码，并传递到浏览器端运行。这些视图无法后续接收通知（调用） 在使用RIA时，View完全运行在浏览器中，View与服务器端只有数据的交互，同样不能接收Model的通知（调用） 为了解决这一问题，MVC2架构出现了，MVC2将View和Model完全解耦，两者之间的交互完全通过Controller间接完成。MVC2中三者的调用关系图如下： 随着基于JavaScript的UI框架以及WebSocket等协议的兴起，现在很多应用抛弃了服务器端脚本技术。View和Controller之间的通信完全基于数据而不是函数调用，WebSocket支持双向通信，这意味着Model在数据发生变化时即时通知Controller，由后者推送给View成为可能。这样的应用场景导致MVC架构又有了新的变化： 经典应用 Servlet与JSP <a class="read-more" href="https://blog.gmem.cc/mvc-pattern">[...]</a></p>
<p>The post <a rel="nofollow" href="https://blog.gmem.cc/mvc-pattern">MVC模式</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></description>
				<content:encoded><![CDATA[<div class="wri_content_clear_both"><div class="blog_h2"><span class="graybg">模式说明</span></div>
<div class="blog_h3"><span class="graybg">经典的MVC模式</span></div>
<p>MVC，即模型-视图-控制器，是一种用于用户界面设计/展示层的架构模式，起初出现在Smalltalk。MVC模式的核心是利用控制器作为中介，将视图和模型解耦。</p>
<p>MVC模式中三者的职责分工明确：</p>
<ol>
<li>模型（Model）：持有<span style="background-color: #c0c0c0;">所有的数据、状态和程序逻辑</span>，模型<span style="background-color: #c0c0c0;">不会感知到视图和控制器</span>（下层组件不依赖于上层）。模型<span style="background-color: #c0c0c0;">提供了操作和检索状态的接口</span>，并且将<span style="background-color: #c0c0c0;">状态改变信息推送给观察者</span>（视图），在某些设计中，视图需要的数据被一同推送</li>
<li>视图（View）：用来呈现模型，视图通常<span style="background-color: #c0c0c0;">直接从模型中获取</span>它需要显示的状态和数据</li>
<li>控制器（Controller）：负责<span style="background-color: #c0c0c0;">获取用户输入</span>，并解读其对于模型的意义。控制器也可能<span style="background-color: #c0c0c0;">直接要求视图</span>做出改变。控制器不应当包含业务逻辑</li>
</ol>
<p>注意和传统的模型含义不同，MVC中的模型不仅仅是指数据对象。以播放器为例，播放状态、当前歌曲、播放行为等都属于模型的组成部分。</p>
<p>三者的调用关系图如下：</p>
<p><img class="aligncenter size-full wp-image-7867" src="https://blog.gmem.cc/wp-content/uploads/2008/03/patterns_MVC.png" alt="patterns_MVC" width="645" height="411" /></p>
<p>上图虽然有箭头从Model指向View，但是这是一种松耦合的、基于观察者模式的通知方式。此外，某些设计中把<span style="background-color: #c0c0c0;">Controller也作为Model的观察者</span>，图中没有标出。</p>
<p>一般MVC中会用到三种设计模式：</p>
<ol>
<li>观察者模式：Model作为事件源，View、Controller作为监听器</li>
<li>策略模式：对于View来说，Controller是具体策略，如果需要改变行为，可以更换一个Controller</li>
<li>组合模式：View中的GUI控件一般都呈现出树状组合关系</li>
</ol>
<div class="blog_h3"><span class="graybg">MVC2</span></div>
<p>经典的MVC模式适用于单机桌面程序的开发，由于Model、View运行在统一进程中，因而互相之间基于函数调用的通信很方便。在常见的Web应用场景中，Model是无法通知到View的，因为：</p>
<ol>
<li>在使用服务器端脚本（PHP、JSP、ASP等）作为视图组件的情况下，这些视图都是一次性生成的过程，结果是HTML代码，并传递到浏览器端运行。这些视图无法后续接收通知（调用）</li>
<li>在使用RIA时，View完全运行在浏览器中，View与服务器端只有数据的交互，同样不能接收Model的通知（调用）</li>
</ol>
<p>为了解决这一问题，MVC2架构出现了，MVC2将View和Model完全解耦，两者之间的交互完全通过Controller间接完成。MVC2中三者的调用关系图如下：</p>
<p><img class="aligncenter size-full wp-image-7880" src="https://blog.gmem.cc/wp-content/uploads/2008/03/patterns_MVC2.png" alt="patterns_MVC2" width="536" height="362" /></p>
<p>随着基于JavaScript的UI框架以及WebSocket等协议的兴起，现在很多应用抛弃了服务器端脚本技术。View和Controller之间的通信完全基于数据而不是函数调用，WebSocket支持双向通信，这意味着Model在数据发生变化时即时通知Controller，由后者推送给View成为可能。这样的应用场景导致MVC架构又有了新的变化：</p>
<p><a href="/wp-content/uploads/2008/03/patterns_MVC2_2.png"><img class="aligncenter size-full wp-image-7882" src="https://blog.gmem.cc/wp-content/uploads/2008/03/patterns_MVC2_2.png" alt="patterns_MVC2_2" width="536" height="362" /></a></p>
<div class="blog_h2"><span class="graybg">经典应用</span></div>
<div class="blog_h3"><span class="graybg">Servlet与JSP</span></div>
<p>JavaEE中的Servlet与JSP技术可以用来构建MVC模式，其中Servlet充当Controller、JSP充当View、后端的Bean则充当Model：</p>
<p><img class="aligncenter size-full wp-image-7884" src="https://blog.gmem.cc/wp-content/uploads/2008/03/patterns_MVC_Servlet.png" alt="patterns_MVC_Servlet" width="621" height="289" /></p>
<div class="blog_h3"><span class="graybg">Struts 1.x</span></div>
<p>Struts 是早期的Java Web框架，其内置了MVC模式的支持。Struts的核心接口是Action，它是一个HTTP请求与相应业务逻辑之间的适配器，作为Controller的RequestProcessor负责把请求分发给合适的Action；Struts没有对View和Model建模，但是在视图方面提供了多种标签库，简化开发。在Struts，ActionForm被用来作为数据传输对象，可以在Model和View之间传递信息。Struts的核心类图如下：</p>
<p><img class="aligncenter size-full wp-image-7888" src="https://blog.gmem.cc/wp-content/uploads/2008/03/patterns_MVC_struts.png" alt="patterns_MVC_struts" width="100%" /></p>
<div class="blog_h3"><span class="graybg"><a id="struts2"></a>Struts 2.x</span></div>
<p>Struts2源于Webwork框架，它朝向零配置的方向发展，原先需要通过XML进行的配置，现在都可以使用Annotation完成。在Struts2中Controller的角色由FilterDispatcher承担，与Struts1中的ActionServlet不同，该类是一个Servlet过滤器；Model角色部分由Action类承担；View角色则部分由Result接口承担。</p>
<p>Struts2最大的不同是，Action没有接口约束，它的角色（该角色实质是由它的一个方法承担）也变成Model，框架通过反射调用之。Action类上可以通过Annotation附加大量元数据信息，例如Action负责哪些请求的处理，请求处理完毕后转向什么页面，下面是一个例子：</p>
<pre class="crayon-plain-tag">import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.ExceptionMapping;
import org.apache.struts2.convention.annotation.ExceptionMappings;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;

import com.opensymphony.xwork2.ActionSupport;

@ParentPackage ( "struts-default" )
@Namespace ( "/web-manager" )
@Results ( { @Result ( name = "success", location = "/main.jsp" ),
        @Result ( name = "error", location = "/error.jsp" ) } )
@ExceptionMappings ( { @ExceptionMapping ( exception = "java.lang.RuntimeException", result = "error" ) } )
public class LoginAction extends ActionSupport
{
    private static final long serialVersionUID = 1L;

    @Action ( "login" )
    public String login() throws Exception
    {
        return SUCCESS;
    }

    @Action ( value = "add", results = { @Result ( name = "success", location = "/index.jsp" ) } )
    public String add() throws Exception
    {
        return SUCCESS;
    }
}</pre>
<p>Struts2的类图如下（使用带标签的序号说明了某个场景下的调用顺序）：</p>
<p><img class="aligncenter size-full wp-image-7894" src="https://blog.gmem.cc/wp-content/uploads/2008/03/patterns_MVC_Struts2.png" alt="patterns_MVC_Struts2" width="100%" /></p>
<p>可以看到，Struts2处理HTTP请求的大致流程如下：</p>
<ol>
<li>FilterDispatcher拦截到来自Servlet容器的HTTP请求，创建ActionContext，该对象是Action执行的上下文，并依据HttpRequest和ConfigurationManager获取ActionMapping，然后调用Dispatcher.serviceAction()，进行分发处理</li>
<li>ActionMapping知道哪个类的方法负责处理当前请求，Dispatcher根据ActionMapping创建extraContext，这是一个简单的Map，然后根据extraContext创建ActionProxy，后者是代理模式的实现。Struts2使用的代理类是StrutsActionProxy。Dispatcher调用ActionProxy.execute()，将请求的处理权转给StrutsActionProxy</li>
<li>StrutsActionProxy没有任何状态，因而不需要为每次请求重新创建它，该代理会在请求处理前后设置/恢复线程本地的ActionContext信息，这样在整个处理期间，ActionContext都不需要通过方法参数传递了。代理通过调用ActionInvocation.invoke()，转移请求处理器</li>
<li>ActionInvocation是Structs2请求处理的核心，主要干三件事情：
<ol>
<li>调用Interceptor链条，对请求进行处理，这里是职责链模式的应用</li>
<li>通过反射调用Action的方法，Action是用户程序的主要扩展点</li>
<li>调用Result，处理视图</li>
</ol>
</li>
</ol>
<div class="blog_h3"><span class="graybg"><a id="springmvc"></a>Spring MVC</span></div>
<p>Spring的MVC框架和Struct2的思想很相似，都是倾向于走向零配置、大量使用注解。Spring MVC中的Controller类与Struct2的Action在功能上是相当的，但是Spring MVC倾向于将其划分到C而不是M；DispatcherServlet是Spring MVC的（核心）控制器角色；ModelAndView类对V、M进行了通用建模，不过很明显了，Spring MVC把Model的概念弱化了，在它这里，M仅仅是DTO。</p>
<p>SpringMVC的处理流程比Struts2清晰简明，逻辑一直把握在DispatcherServlet手上：</p>
<ol>
<li>DispatcherServlet使用模板方式模式的变体来组织整个请求处理过程，它定义了整体处理算法：<span style="background-color: #c0c0c0;">请求预处理⇨设置属性⇨调用拦截器预处理⇨调用Handler⇨调用拦截器后处理⇨处理渲染⇨调用拦截器完成处理</span>。这些具体步骤中，很大一部分交由用户提供的拦截器、Handler完成。Handler可以是任意Java类，只需要将其标记@Controller注解并扫描。</li>
<li>DispatcherServlet能够接受到Spring事件通知，监听器是它父类的一个内部类ContextRefreshListener，该内部类转调了DispatcherServlet的onApplicationEvent</li>
<li>DispatcherServlet设置当前HttpServletRequest对象的若干属性，例如它关联的ApplicationContext</li>
<li>DispatcherServlet执行拦截器链条，这是一个职责链模式的变体，具有3条职责路径（预处理、后处理、完成后处理），首先执行preHandle()进行预处理</li>
<li>DispatcherServlet调用HandlerAdapter.handle()处理请求，最常用的HandlerAdapter实现是AnnotationMethodHandlerAdapter，基于注解使用Spring MVC时，会自动使用该类。从名字上可以看出，这是一个适配器模式，它基于反射机制，对Handler继续完全的适配：
<ol>
<li>Handler的入参数量、类型都是任意的，HandlerAdapter需要把HttpServletRequest、HttpServletResponse等对象适配为这些类型。AnnotationMethodHandlerAdapter依靠反射机制和各种注解完成这一适配</li>
<li>Handler的返回值类型是任意的，HandlerAdapter需要将其适配为ModelAndView类型</li>
</ol>
</li>
<li>DispatcherServlet执行拦截器链条的postHandle()进行后处理</li>
<li>DispatcherServlet调用View.render()执行渲染</li>
<li>DispatcherServlet执行拦截器链条的afterCompletion()进行最终处理</li>
</ol>
<p>Spring MVC的主要类图如下：</p>
<p><img class="aligncenter size-full wp-image-7900" src="https://blog.gmem.cc/wp-content/uploads/2008/03/patterns_MVC_Spring.png" alt="patterns_MVC_Spring" width="100%" /></p>
<p>下面是一个简单的Handler的例子，可以看到和Struts的Action是很类似的：</p>
<pre class="crayon-plain-tag">import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping ( "/web-manager" )
public class LoginController
{

    @RequestMapping ( value = "login/{mode}", method = { RequestMethod.POST } )
    @ResponseBody
    public Object login( @PathVariable String mode, @RequestParam String uname )
    {
        return null;
    }
}</pre>
<div class="blog_h3"><span class="graybg">ExtJS的MVC框架</span></div>
<p>ExtJS是一个基于JavaScript的框架，它提供了大量基于Web的UI控件，ExtJS还内置了MVC模式，具体可以参考：<a href="/mvc-framework-of-extjs-4">ExtJS 4的MVC框架</a></p>
<p>在这里我们可以注意到，理解MVC的概念不能死板。假设我们同时使用Spring MVC和ExtJS MVC，那么这两个框架什么关系呢？岂不是重复了？实际上，对于ExtJS来说，整个服务器端应用程序都属于M的一部分；而对于Spring来说，整个ExtJS和Spring的JsonView都属于V的部分。角度不同，思考也就不同，所谓横看成岭侧成峰嘛。</p>
</div><p>The post <a rel="nofollow" href="https://blog.gmem.cc/mvc-pattern">MVC模式</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.gmem.cc/mvc-pattern/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
