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

mvc架构是安卓的经典架构模式,它是观察者模式的一个典型应用场景。今天我就用java程序来简单模拟mvc架构的实现。

首先,简单说下什么是mvc架构。
mvc架构由model,view和controller三者组成,基于职责分离的原则,三者分别承担不同的职责。
view:负责界面显示逻辑
model:负责数据封装以及相关业务逻辑
controller:view与mode的中间者,负责传递事件,有时候可承担简单的业务逻辑

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

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

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

下面是mvc架构的依赖关系图:

这里写图片描述

然后是MVC架构的调用关系图:

这里写图片描述

基于MVC架构的依赖关系和调用关系图,我用java程序来简单模拟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:

/**
 * 观察者接口
 */
public interface IObserver {
    /**
     * 观察者方法
     * @param subject:被观察者抽象层对象
     * @param o:额外信息
     */
    public void update(IObservable observable, Object o);
}

IObservable:

/**
 * 被观察者接口
 */
public interface IObservable {

    public void addObserver(IObserver observer);

    public void deleteObserver(IObserver observer);

    public void notifyUpdate();

    public void notifyUpdate(Object object);
}

IViewAction:

/**
 * 定义视图的基本行为 
 */
public interface IViewAction {
    /**
     * 刷新视图
     * @param baseModel
     * @param o
     */
    public void refreshView(BaseModels baseModel, Object o);
}

IModelAction:

/**
 * 定义model的基本行为
 */
public interface IModelAction {
    /**
     * model请求数据
     */
    public void requestData();
}

BaseView:

public abstract class BaseViews implements IObserver,IViewAction{
    protected Controller controller;// 控制器

    public BaseViews() {
        controller = new Controller(this);
    }

    @Override
    public void update(IObservable observable, Object o) {
        if(observable instanceof BaseModels) {
            BaseModels baseModel=(BaseModels)observable;
            if(baseModel.isChanged()) {
            refreshView(baseModel,o);
            }
        }

    }
}

BaseModel:

public abstract class BaseModels implements IObservable, IModelAction {
    private List<IObserver> mObservers;
    private boolean mIsChanged;

    public BaseModels() {
        mObservers = new ArrayList<IObserver>();
    }

    @Override
    public void addObserver(IObserver observer) {
        if (mObservers == null) {
            return;
        }

        mObservers.add(observer);
    }

    @Override
    public void deleteObserver(IObserver observer) {
        if (mObservers == null || mObservers.size() == 0) {
            return;
        }

        mObservers.remove(observer);

    }

    @Override
    public void notifyUpdate() {
        notifyUpdate(null);
    }

    @Override
    public void notifyUpdate(Object object) {

        if (mObservers == null || mObservers.size() == 0) {
            return;
        }

        for (IObserver observer : mObservers) {
            observer.update(this, object);
        }

    }

    public boolean isChanged() {
        return mIsChanged;
    }

    public void setChanged(boolean mIsChanged) {
        this.mIsChanged = mIsChanged;
    }

}

Controller:

public class Controller {
    private BaseViews view;
    private BaseModels model;

    public Controller(BaseViews view) {
        super();
        this.view = view;

        model = new Model();
        // 将view与model绑定
        model.addObserver(view);
    }

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

        model.requestData();

    }

}

View:

public class View extends BaseViews {


    public void touch() {
        System.out.println("模拟屏幕操作,触发响应事件,将事件传给controller处理");
        // 将事件传给controller处理
        controller.doSomething();
    }

    /**
     * 刷新界面
     */
    @Override
    public void refreshView(BaseModels baseModel, Object o) {
        if (baseModel instanceof Model) {
            Model model = (Model) baseModel;
            String name = model.getName();
            String display = model.getDisplay();
            System.out.println("收到Model通知,更新界面");
            System.out.println("Model包含以下数据:");
            System.out.println("name=" + name + " ,display=" + display);
        }

    }

}

Model:

public class Model extends BaseModels {
    /**
     * Model的一些属性
     */
    private String name;// 名字
    private String display;// 展示数据


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDisplay() {
        return display;
    }

    public void setDisplay(String display) {
        this.display = display;
    }

    @Override
    public void requestData() {
        // 模拟model更新
        setName("杰伦");
        setDisplay("哎呦,不错哦");

        // 设置改变
        setChanged(true);
        System.out.println("model发生了改变,通知view更新");
        notifyUpdate();
    }

}

Client:

public class Client {

    public static void main(String[] args) {
        View view = new View();
        // 模拟点击界面
        view.touch();

    }

}

运行截图:
这里写图片描述

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

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

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

github地址:https://github.com/hyhdy/mvc_java

展开阅读全文

没有更多推荐了,返回首页