复合模式:MVC模式 gaunthan Posted on Feb 10 2017 ? Design Patterns ? > 模式通常被一起使用,并被组合在同一个设计解决方案中。**复合模式**(Compound Pattern)在一个解决方案中结合两个或多个模式,以解决一般或重复发生的问题。 ## MVC模式 > MVC(Model-View-Controller,模型-视图-控制器)模式将业务逻辑、数据和界面显示分离,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。 MVC是最出名的复合模式之一,结合了观察者模式、策略模式和组合模式,它包含三个组件: 组件|说明 --|-- 模型|模型持有所有的数据、状态和程序逻辑。模型没有注意到视图和控制器,虽然它提供了操作和检索状态的接口,并且发送状态改变通知给观察者(视图)。 视图|用来呈现模式。视图通常直接从模型中取得它需要显示的状态和数据。 控制器|取得用户的输入并解读其对模型的请求。  从上图中可发现: 1. 用户和视图交互。 视图是模型的窗口。当用户对视图做一些事时(如按下按钮),视图就告诉控制器用户做了什么。控制器会负责处理。 2. 控制器要求模型改变状态。 控制器会解读用户的动作,并告知模型如何作出相应的动作。 3. 控制器也可能要求视图做改变。 当控制器从视图接收到某一动作,结果可能是它也需要告诉视图改变其结果。比方说,控制器可以将界面上的某些按钮或菜单项变成有效或无效。 4. 当模型状态改变时,模型会通知视图。 不管是用户进行的动作还是内部有了某些改变,只要模型内的东西改变了,模型就会通知视图它的状态改变了。 5. 视图向模型询问状态。 视图直接从模型取得它显示的状态。当控制器请求视图改变时,视图也可能向模型询问某些状态。 显然,**视图是模型的观察者**。那控制器可以是模型的观察者吗?在某些设计中,控制器会向模型注册。模型一经改变,就会通知控制器。当模型直接影响到用户界面时,就会这么做。比如,模型内的某些状态可以支配界面的某些项目变成有效或无效,如果这样,要求视图更新相应显示其实就是控制器的事。 ### MVC里的观察者模式 模型实现了[观察者模式](http://gaunthan.leanote.com/post/%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F-Observer-Pattern),当状态改变时,相关对象将持续更新。使用观察者模式,可以让模型完全独立于视图和控制器。同一个模型可以使用不同的视图,甚至可以同时使用多个视图。  ### MVC里的策略模式 视图和控制器实现了[策略模式](http://gaunthan.leanote.com/post/%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F-Strategy-Pattern):视图是一个对象,可以被调整使用不同的策略,而控制器提供了策略。视图只关心系统中可视的部分,对于任何界面行为,都委托给控制器处理。使用策略模式也可以让视图和控制器之间的关系解耦,因为控制器负责和模型交互来传递用户的请求。对于工作是怎么完成的,视图毫不知情。  ### MVC里的组合模式 视图内部使用[组合模式](http://gaunthan.leanote.com/post/%E7%BB%84%E5%90%88%E6%A8%A1%E5%BC%8F)来管理窗口、按钮以及其他显示组件。显示包括了窗口、面板、按钮、文本标签等。每个显示组件如果不是组合节点(例如窗口),就是叶节点(例如按钮)。当控制器告诉视图更新时,只需告诉视图最顶层的组件即可,组合会去处理其余的事。  ### 使用适配器模式 适配器是使用MVC时经常附带用到的技巧:使用[适配器模式](http://gaunthan.leanote.com/post/%E9%80%82%E9%85%8D%E5%99%A8%E6%A8%A1%E5%BC%8F)将模型适配成符合现有视图和控制器需要的模型。 ## MVC与Web:Model 2 Web开发人员也都在适配MVC,使它符合浏览器-服务器模型。我们称这样的适配器为“**Model 2**”,并使用Servlet和JSP技术的结合,来达到MVC的分离效果,就像传统的GUI。  1. 用户发出一个会被Servlet收到的HTTP请求。 用户利用网页浏览器发出HTTP请求。这通常牵涉到送出表单数据,例如用户名和密码。Servlet收到这样的数据,并解析数据。 2. Servlet扮演控制器。 Servet扮演控制器的角色,处理用户的请求,通常会向模型(一般是数据库)发出请求。处理结果往往以JavaBean的形式打包。 3. 控制器将控制权交给视图。 视图就是JSP,而JSP唯一的工作就是产生页面,表现模型的视图以及进一步动作所需要的所有控件。 4. 视图从JavaBean中获取模型数据。 5. 视图通过HTTP将页面返回给浏览器。 页面返回浏览器,作为视图显示出来。用户若提出进一步的请求,将以同样的方式处理。 Model 2看起来不像是“教科书”上的MVC,但某些部分还是存在的,只是为了反映Web浏览器模型的特质而经过了调整:  ### 观察者 视图不再是经典意义上的模型的观察者,它没有向模型注册以接收状态改变通知。但是当模型改变时,视图的确间接地从控制器收到了相当于通知的东西。控制器甚至把Bean送给视图,这允许视图取得模型的状态。 考虑到浏览器模型,随时通知视图进行更新是没有意义的,因为视图只在HTTP响应返回到浏览器时需要一个状态信息的更新。只有当页面被创建和返回时,创建视图并结合模型状态才是合理的做法。 ### 策略 在Model 2中,策略对象仍然是控制器Servlet,但它不像传统的做法那样直接和视图结合。就是说,策略对象为视图实现行为,当我们想要有不同的行为时,可以直接把控制器换掉。 ### 组合 像Swing GUI,视图是利用许多图形组件一层一层叠起来的。但是在这里,则是由网页浏览器呈现 HTML 描述。尽管如此,内部还是很类似一个组合的对象系统。 ## References - 弗里曼弗里曼谢拉贝茨 O'ReillyTaiwan 公司 UMLChina. Head First 设计模式 [M]. 中国电力出版社, 2007. 赏 Wechat Pay Alipay [转] 使用GIMP调节照片亮度的简单方法 策略模式