观察者模式的应用:模拟MVC架构的实现

Posted 辉猿走壁

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了观察者模式的应用:模拟MVC架构的实现相关的知识,希望对你有一定的参考价值。

之前讲过观察者模式,今天想讲下观察者模式的一个典型应用场景,MVC架构的实现。

首先,简单说下什么是MVC。

MVC是model,view和controller三个对象的简称,基于职责分离的原则,三者分别承担不同的工作。

view:负责界面显示逻辑 model:负责数据封装以及相关业务逻辑 controller:view与mode的中间者,负责传递事件,有时候可承担简单的业务逻辑

当用户操作界面时,比如点击某个按钮,会把点击事件传给controller,controller通知model进行更新,当model更新完毕后,需要通知view来刷新界面。

因此,model和view需要有一套机制来保证model的数据变更能够实时同步到view显示。

所以,观察者模式便在mvc模式中派上了用场。

MVC架构的依赖关系图

MVC架构的调用关系图

观察者模式的应用:模拟MVC架构的实现

基于MVC架构的依赖关系和调用关系图,我用java程序来简单模拟MVC架构的实现。

首先看看类图:

观察者模式的应用:模拟MVC架构的实现

简单讲解下每个类的作用:

观察类图会发现自顶向下分成了三个层次:

1.顶层抽象:定义观察者抽象层代码和view,model的基本行为接口。

IObserver:抽象观察者接口 IObservable:抽象被观察者接口 IViewAction:视图行为接口,定义视图的基本行为 IModelAction:Model行为接口,定义model的基本操作

2.view,model抽象层

BaseView:view基类,view的抽象层,实现IObserver接口

BaseModel:model基类,model的抽象层,实现IObservable接口

3.具体实现层

Controller:控制器,依赖于BaseView和BaseModel,通过抽象依赖的方式,与具体view和具体model解耦,使得controller更容易复用

view:具体view,继承BaseView

Model:具体model,继承BaseModel。

然后这是源代码,注释已经写得很清楚,我就不解释了:

IObserver:

 
   
   
 
  1. /**

  2. * 观察者接口

  3. */

  4. public interface IObserver {

  5. /**

  6. * 观察者方法

  7. * @param subject:被观察者抽象层对象

  8. * @param o:额外信息

  9. */

  10. public void update(IObservable observable, Object o);

  11. }

IObservable:

 
   
   
 
  1. /**

  2. * 被观察者接口

  3. */

  4. public interface IObservable {


  5. public void addObserver(IObserver observer);


  6. public void deleteObserver(IObserver observer);


  7. public void notifyUpdate();


  8. public void notifyUpdate(Object object);

  9. }

IViewAction:

 
   
   
 
  1. /**

  2. * 定义视图的基本行为

  3. */

  4. public interface IViewAction {

  5. /**

  6. * 刷新视图

  7. * @param baseModel

  8. * @param o

  9. */

  10. public void refreshView(BaseModels baseModel, Object o);

  11. }

IModelAction:

 
   
   
 
  1. /**

  2. * 定义model的基本行为

  3. */

  4. public interface IModelAction {

  5. /**

  6. * model请求数据

  7. */

  8. public void requestData();

  9. }

BaseView:

 
   
   
 
  1. public abstract class BaseViews implements IObserver,IViewAction{

  2. protected Controller controller;// 控制器


  3. public BaseViews() {

  4. controller = new Controller(this);

  5. }


  6. @Override

  7. public void update(IObservable observable, Object o) {

  8. if(observable instanceof BaseModels) {

  9. BaseModels baseModel=(BaseModels)observable;

  10. if(baseModel.isChanged()) {

  11. refreshView(baseModel,o);

  12. }

  13. }


  14. }

  15. }

BaseModel:

 
   
   
 
  1. public abstract class BaseModels implements IObservable, IModelAction {

  2. private List<IObserver> mObservers;

  3. private boolean mIsChanged;


  4. public BaseModels() {

  5. mObservers = new ArrayList<IObserver>();

  6. }


  7. @Override

  8. public void addObserver(IObserver observer) {

  9. if (mObservers == null) {

  10. return;

  11. }


  12. mObservers.add(observer);

  13. }


  14. @Override

  15. public void deleteObserver(IObserver observer) {

  16. if (mObservers == null || mObservers.size() == 0) {

  17. return;

  18. }


  19. mObservers.remove(observer);


  20. }


  21. @Override

  22. public void notifyUpdate() {

  23. notifyUpdate(null);

  24. }


  25. @Override

  26. public void notifyUpdate(Object object) {


  27. if (mObservers == null || mObservers.size() == 0) {

  28. return;

  29. }


  30. for (IObserver observer : mObservers) {

  31. observer.update(this, object);

  32. }


  33. }


  34. public boolean isChanged() {

  35. return mIsChanged;

  36. }


  37. public void setChanged(boolean mIsChanged) {

  38. this.mIsChanged = mIsChanged;

  39. }


  40. }

Controller:

 
   
   
 
  1. public class Controller {

  2. private BaseViews view;

  3. private BaseModels model;


  4. public Controller(BaseViews view) {

  5. super();

  6. this.view = view;


  7. model = new Model();

  8. // 将view与model绑定

  9. model.addObserver(view);

  10. }


  11. public void doSomething() {

  12. System.out.println("controller响应view的界面操作事件,通知model更新");


  13. model.requestData();


  14. }


  15. }

View:

 
   
   
 
  1. public class View extends BaseViews {



  2. public void touch() {

  3. System.out.println("模拟屏幕操作,触发响应事件,将事件传给controller处理");

  4. // 将事件传给controller处理

  5. controller.doSomething();

  6. }


  7. /**

  8. * 刷新界面

  9. */

  10. @Override

  11. public void refreshView(BaseModels baseModel, Object o) {

  12. if (baseModel instanceof Model) {

  13. Model model = (Model) baseModel;

  14. String name = model.getName();

  15. String display = model.getDisplay();

  16. System.out.println("收到Model通知,更新界面");

  17. System.out.println("Model包含以下数据:");

  18. System.out.println("name=" + name + " ,display=" + display);

  19. }


  20. }


  21. }

Model:

 
   
   
 
  1. public class Model extends BaseModels {

  2. /**

  3. * Model的一些属性

  4. */

  5. private String name;// 名字

  6. private String display;// 展示数据



  7. public String getName() {

  8. return name;

  9. }


  10. public void setName(String name) {

  11. this.name = name;

  12. }


  13. public String getDisplay() {

  14. return display;

  15. }


  16. public void setDisplay(String display) {

  17. this.display = display;

  18. }


  19. @Override

  20. public void requestData() {

  21. // 模拟model更新

  22. setName("杰伦");

  23. setDisplay("哎呦,不错哦");


  24. // 设置改变

  25. setChanged(true);

  26. System.out.println("model发生了改变,通知view更新");

  27. notifyUpdate();

  28. }


  29. }

Client:

 
   
   
 
  1. public class Client {


  2. public static void main(String[] args) {

  3. View view = new View();

  4. // 模拟点击界面

  5. view.touch();


  6. }


  7. }

运行截图:

总结

本来想真正写个安卓程序来实现mvc模式的,但是因为想着方便点就直接用java实现了,所以view是假的view,只是用来模拟用户操作而已。虽然并不是真正的安卓程序,但是这些代码还是具备可移植性的,如果想在安卓程序上应用只需要把view换成真正的view就可以了,其他代码视情况进行适当修改。

可扩展性分析

假如以后想增加新的view和mode,,则只需要增加新的子类,分别继承Baseviewh和BaseModel即可,不需要修改源代码,controller也不需要改,因为controler依赖于BaseView和BaseModel,并不依赖于具体类,符合开闭原则。

缺点

存在多层依赖关系,自顶向下存在三层依赖关系:观察者抽象层:IObserver依赖于IObservable view,model抽象层:BaseView依赖于BaseModel 具体实现层:View依赖于Model 由于这样的关系,所以需要多次使用instanceof进行强制类型转换,影响效率。

https://github.com/hyhdy/mvc_java




长按二维码关注

辉猿走壁码出奇迹


以上是关于观察者模式的应用:模拟MVC架构的实现的主要内容,如果未能解决你的问题,请参考以下文章

MVC代码结构模式moogoDB的学习

使用 Windows 窗体实现 MVC

Unity3D架构之PureMVC

iOS 设计模式(五)-KVO 详解

js设计模式-观察者模式来模拟vue的双向数据绑定

《从零开始学Swift》学习笔记(Day67)——Cocoa Touch设计模式及应用之MVC模式