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