450 likes | 671 Views
MVC 体系结构. 南京大学软件学院 2009. 1. MVC 体系结构. MVC 基本概念及应用领域 MVC 主体结构 MVC 动态特征 MVC 实现 软件体系结构、框架与设计模式 观察者( Observer )设计模式 应用实例. MVC 基本概念:模型 - 视图 - 控制器 (1). MVC ( Model-View-Controller )将一个交互式应用程序分成3个组件 模型:包含核心功能和数据 (核心业务逻辑) 视图:向用户显示信息 控制器:处理用户输入 变更 - 传播机制保证了模型和用户界面之间的一致性. (图形用户界面).
E N D
MVC体系结构 南京大学软件学院 2009 1
MVC体系结构 • MVC基本概念及应用领域 • MVC主体结构 • MVC动态特征 • MVC实现 • 软件体系结构、框架与设计模式 • 观察者(Observer)设计模式 • 应用实例
MVC基本概念:模型-视图-控制器(1) • MVC(Model-View-Controller)将一个交互式应用程序分成3个组件 • 模型:包含核心功能和数据 (核心业务逻辑) • 视图:向用户显示信息 • 控制器:处理用户输入 • 变更-传播机制保证了模型和用户界面之间的一致性 (图形用户界面)
MVC基本概念:模型-视图-控制器(2) • 目的 • 将人机交互从核心功能中分离出来(M) • 模型对用户来说是透明的,用户只需要观察视图(V) • 用户与模型的交互通过控制器提供的安全方法来实现(C)
MVC应用领域 • 具有灵活人-机界面的交互式应用程序 • 可以灵活选择不同的信息显示方式 • 可以灵活选择用户的输入方式 • 针对不同的用户角色,提供不同的用户界面 • 不同用户具有不同权限,操作的方式也有所不同
MVC体系结构 • MVC基本概念及应用领域 • MVC主体结构 • MVC动态特征 • MVC实现 • 软件体系结构、框架与设计模式 • 观察者(Observer)设计模式 • 应用实例
模型(Model) • 封装了内核功能和数据 • 业务逻辑(软件的核心) • 数据以及访问它们的函数(视图组件使用) • 执行特定应用程序处理的过程(控制器代表用户调用) • 模型对于用户来说是不可见的(M与V独立) • 模型独立于特定输出表示或者输入方式(M与C独立) • 用户只能通过控制器操作模型(C是M与V之间的桥梁)
变更-传播机制(1) • 一个模型可对应多个视图 • 如果用户通过一个视图的控制器改变了模型中的数据,那么依赖于该数据的其他视图也应该反映出这样的变化 • 一旦模型的数据发生了变化,模型需要通知所有相关的视图做出相应的变化 • 维护数据的一致性
变更-传播机制(2) • 工作原理: • 模型维护了一个表 • 所有视图还有一些控制器在这个表中登记了对变更通知的需求 • 模型状态的改变将触发变更-传播机制,每个在表中登记的视图和控制器都会收到变更通知 • 这样的方式可以通过观察者(Observer)设计模式完成
视图(View) • 向用户显示信息 • 不同的视图使用不同的方法呈现信息 • 每个视图组件都有一个更新函数,这个函数被模型变更通知激活 • 这个函数被激活(此时模型已经改变)后,将使得视图重新和模型一致 • 在初始化阶段,视图向模型登记请求变更通知(表) • 从模型获得数据 • 通过状态查询函数实现 • 例如:定时刷新
控制器(Controller) • 每个视图有一个相关的控制器组件(一一对应) • 控制器组件接受事件,并翻译成输入 • 事件如何发送到控制器由用户界面平台决定 • 事件被翻译成为对模型或者视图的请求 • 如果控制器的行为依赖于模型的状态,那么控制器也需要向模型登记请求变更通知 • 例如:用户点击按钮,按钮的事件响应函数将采取相应的措施处理用户要求 • 用户仅仅通过控制器与系统交互
注意 • 视图与控制器是一一对应的关系 • 模型与视图是一对多的关系 • 变更-传播机制保持模型与视图、控制器之间状态的一致性
MVC体系结构 • MVC基本概念及应用领域 • MVC主体结构 • MVC动态特征 • MVC实现 • 软件体系结构、框架与设计模式 • 观察者(Observer)设计模式 • 应用实例
Main program Model View model view Controller model,view controller start 动态特征(1):MVC系统的初始化过程
动态特征(2):MVC系统的初始化过程 • 创建模型实例,并初始化其数据 • 创建视图对象,并用对模型的引用作为初始化参数之一 • 视图通过调用附属过程支持变更-传递机制 • 视图创建控制器,此时将模型和视图的引用作为参数传递给控制器初始化过程 • 控制器通过调用附属过程来支持变更-传递机制 • 初始化完成,应用程序开始处理事件
Controller Model View handleEvent service notify display update getData update getData 动态特征(3):输入导致模型变化,并触发变更-传递机制
动态特征(4):输入导致模型变化,并触发变更-传递机制动态特征(4):输入导致模型变化,并触发变更-传递机制 • 控制器接受到事件,解释事件并且启动模型的服务过程(handleEvent、 service) • 模型执行相应的过程,并导致内部状态的变化(notify) • 模型调用其更新过程,向所有登记请求了变更-传播机制的视图和控制器发出通知(update) • 每个视图从模型中读取新数据并且重新显示(getData) • 每个控制器修改自己的行为,比如禁用某个功能 • 最初的控制器恢复控制并从事件处理过程返回
MVC体系结构 • MVC基本概念及应用领域 • MVC主体结构 • MVC动态特征 • MVC实现 • 软件体系结构、框架与设计模式 • 观察者(Observer)设计模式 • 应用实例
MVC实现(1) • 设计并实现模型组件 • 封装内核所需要的数据和功能 • 确定模型的哪一部分应该通过控制器向用户显示,提供访问待显示数据的功能 • 实现核心业务逻辑
MVC实现(2) • 实现变更-传播机制 • 采用观察者(Observer)设计模式 • 每个视图和需要观察模型变更的控制器都在模型中注册自己的观察者(表) • 模型中可以随意添加和删除观察者 • 实现通知各观察者并改变其状态的方法
MVC实现(3) • 设计并实现视图 • 设计视图的外观,并实现画图过程来将视图显示在屏幕上(需要使用用户界面平台的功能) • 实现更新过程来反映模型的变化 • 可以简单地调用画图功能,但是不适应模型频繁变化的情况 • 向更新过程提供一些参数来确定是否重画,以及重画范围 • 可以通过累积变化的方式减少重画的频率 • 还需要实现视图的初始化过程 • 支持变更-传递机制 • 初始化控制器
MVC实现(4) • 设计并实现控制器 • 对于每个视图,指定回应用户动作的系统行为 • 控制器用一个专用的过程来接受并且解释这些用户动作(事件) • 实现事件响应函数
MVC实现(5) • 实现MVC的总体的初始化部分 • 首先创建并初始化模型实例 • 创建和初始化视图实例 • 同时会创建相应的控制器实例 • 初始化之后进入一个循环,或者包含循环的过程
MVC体系结构 • MVC基本概念及应用领域 • MVC主体结构 • MVC动态特征 • MVC实现 • 软件体系结构、框架与设计模式 • 观察者(Observer)设计模式 • 应用实例
软件体系结构:Architecture(1) • 迄今为止还没有一个被大家所公认的定义 • 确定了系统整体结构、层次划分以及不同部分之间的协作等设计考虑 • 是软件设计过程中的第一个层次,常用于总体设计 • MVC是一种软件体系结构
软件体系结构:Architecture(2) • Kruchten指出,软件体系结构有四个角度,它们从不同方面对系统进行描述 • 概念角度:描述系统的主要构件及它们之间的关系 • 模块角度:包含功能分解与层次结构 • 运行角度:描述了一个系统的动态结构 • 代码角度:描述了各种代码和库函数在开发环境中的组织
框架:Framework • 框架不是现成可用的应用系统,而是一个半成品,需要后来的开发人员进行二次开发,实现体功能的应用系统 • 框架构成了通用的、具有一般性的系统主体部分,二次开发人员只是像做填空一样,根据具体业务,完成特定应用系统中与众不同的特殊部分 • 框架比体系结构更具体,更偏重于技术 • 一般来说,确定框架后,软件体系结构也随之确定,而对于同一软件体系结构(比如Struts是基于Web的MVC框架),可以通过多种框架来实现 • MVC不是框架
设计模式:Design Pattern • 设计模式研究的是单一设计问题的解决方法 • 构思如何组合已有的组件,使其发挥出最大的功效 • 描述问题中出现的类和接口,以及它们之间的关系 • 只是思想,不是代码 • 可由不同语言实现,提高代码的可重用性 • MVC不是设计模式
MVC体系结构 • MVC基本概念及应用领域 • MVC主体结构 • MVC动态特征 • MVC实现 • 软件体系结构、框架与设计模式 • 观察者(Observer)设计模式 • 应用实例
观察者(Observer)设计模式:通知状态变化(1) • 需求 • 有多个类的状态依赖于一个主类的状态变化 • 解决方案 • 多个类作为观察者,主类作为被观察者 • 设计一个观察者接口,其中包含一个更新方法,所有观察者都实现该接口 • 在主类中保存一个观察者队列,存放所有观察者对象 • 一旦主类状态发生变化,就通知观察者队列改变相应类的状态
观察者(Observer)设计模式:通知状态变化(3) • Observer的设计 • 接口:每个具体的观察者子类都必须实现自己的更新方法 • 抽象类:更新方法为抽象,但有一些其它方法是所有观察者子类所共有,可以在基类中实现 • 具体基类:基类中实现默认的更新方法,需要自己独特的更新方法的子类覆盖基类的更新方法
观察者(Observer)设计模式:通知状态变化(4) • 每当新建一个观察者(Observer)时,就要将它注册(addObserver方法)给被观察者(Subject) • 一旦被观察者(Subject)的状态发生变化,就必须通知(notifyObservers方法) 所有观察者(Observer) • 通知的同时,notifyObservers方法循环调用所有观察者的update方法,更新观察者
MVC体系结构 • MVC基本概念及应用领域 • MVC主体结构 • MVC动态特征 • MVC实现 • 软件体系结构、框架与设计模式 • 观察者(Observer)设计模式 • 应用实例
应用实例(1) • 需求 • 有两个窗口,每个窗口分别有一个标签和一个按钮 • 点击其中一个窗口中的按钮,可以使标签的字体增大,点击另一个可以使其字体减小 • 一个窗口对字体的改变必须立即反映在另一个窗口中 • 目的 • 采用MVC模式设计实现 • 使用观察者(Observer)设计模式模拟变更-传播机制
应用实例(3):Observer接口 interface Observer { //更新函数 public void update(); }
应用实例(4):M类 class M { private int size = 20; //字体大小 //使字体变大 public void enlarge(){ this.setSize( this.getSize() + 5 ); } //使字体变小 public void abridge(){ this.setSize( this.getSize() - 5 ); }
应用实例(5):M类 //观察者队列 private List<Observer> observers = new ArrayList<Observer>(); public void addObservers( Observer observer ){ this.observers.add( observer ); } //当模型有变更时,通知所有观察者改变相应的视图 public void notifyObservers(){ Iterator<Observer> iter = this.observers.iterator(); while( iter.hasNext() ){ iter.next().update(); } } …… }
应用实例(6):C1类 class C1 implements ActionListener { //一个控制器与一个视图和一个模型对应 private V1 v1; private M m; //构造函数 public C1( V1 v1, M m ){ this.m = m; this.v1 = v1; } //向模型注册此控制器对应的视图的观察者 public void register(){ this.m.addObservers( this.v1 ); }
应用实例(7):C1类 /** * 实现事件监听器, * 当点击按钮时,增大标签的字体 */ public void actionPerformed( ActionEvent e ){ this.m.enlarge(); this.m.notifyObservers(); } …… }
应用实例(8):V1类 class V1 implements Observer { JLabel label = new JLabel( "MVC" ); JButton button = new JButton( "增大字体" ); private C1 c1; //与视图V1对应的控制器 //实现Observer接口,当有变更时,改变相应视图 public void update(){ Font font = new Font( this.label.getText(), c1.getM().getStyle(), c1.getM().getSize() ); this.label.setFont( font ); }
应用实例(9):V1类 public V1(M m){ //实例化一个链接此视图和模型的控制器 c1 = new C1( this, m ); //注册此视图的观察者到模型中 c1.register(); …… } …… }
应用实例(10):主程序Test • C2与V2的实现与C1和V1的实现相似 public class Test { /** * @param args */ public static void main(String[] args) { M m = new M(); V1 v1 = new V1(m); V2 v2 = new V2(m); } }