1. 程式人生 > >觀察者模式的應用:模擬MVC架構的實現

觀察者模式的應用:模擬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進行強制型別轉換,影響效率。