學習MV*架構模式

如何寫出靈活、可複用、可擴展、可維護的代碼呢?

前言:要想寫出靈活、可複用、可擴展、可維護的代碼實屬不易,到了這個境界那便是是傳說中的程序員了(見下圖)!哈哈哈。。。希望大家每天都向她發起衝鋒的號角,直至勝利的那一天!前一段時間研究了很長一段時間面向對象,感覺收穫頗豐,站在巨人的肩膀上看對象,感覺妙極了。今天再次站在巨人的肩膀上看設計模式,勵志要把對象設計的更好!!!!!

"傳說中的程序員"

面向對象設計原則

  • 單一責任原則:個類有且只有一個職責
  • 開閉原則:軟件實體(類,模塊,函數等)應該對擴展開放,對修改關閉
  • 里氏替換原則:子類型必須能夠替換它們的基類(使用基類引用的函數必須能夠使用派生類而無須瞭解派生類)
  • 接口隔離原則:用戶不應該被迫依賴他們不使用的接口
  • 依賴倒置原則:高層次的模塊不應該依賴於低層次的模塊,而是,都應該依賴於抽象
  • 組合替代繼承:用組合比用繼承好
  • 笛米特法則:類對其它類知道的越少越好
  • 共同封閉原則:相關類應該一起打包
  • 穩定抽象原則:類越穩定,就越應該是抽象類

詳情參見下文:

面向對象設計模式

入門須知

設計模式並不是被科學家發明和創造的東西。他們只是被“發現”而已。也就是說,對任何一個普通的問題場景,肯定會有一些好的設計方案。如果我們能識別出一個能解決某個新問題的面向對象設計,那我們就定義了一個新的設計模式。

設計模式不是基於理論發明的。相反,總是先有問題場景,再基於需求和情景不斷演化設計方案,最後把一些方案標準化成“模式”。所以,我們討論每一個設計模式時,要儘量用生活中的真實問題來理解和分析。然後嘗試一步步地闡述設計,並以一個能匹配某些模式的設計收尾。

媳婦: 我有點好奇。你不是說有很多模式麼,幹嘛先說橋樑模式呢?有什麼特別重要的原因嗎?
丈夫: 問得好。我從橋樑模式開始,而不是其它模式,只有一個原因。我覺得它是所有面向對象設計模式的基礎。因爲:
它能教你如何抽象地思維,這可是OO設計模式的關鍵。
它實現了基本的OOD原則。
它很好理解。
如果你能正確地理解它,學習其它模式就易如反掌了。

詳情參見下文:

橋接模式

1、橋接模式:將抽象部分和它的實現部分分離,使它們都可以獨立的變化。簡單粗暴的說,就是抽象對外提供調用的接口;對外隱瞞實現部分,在抽象中引用實現部分,從而實現抽象對實現部分的調用,而抽象中引用的實現部分可以在今後的開發過程中,切換成別的實現部分。(《設計模式:可複用面向對象軟件的基礎》)

2、UML類圖
UML類圖

3、代碼實例:(引用原文代碼,只是添加註釋)

/*
** FileName     : BridgePatternDemo
** Author       : Jelly Young
** Date         : 2013/12/4
** Description  : More information (http://www.jellythink.com/)
** Author       : Aidan Dai
** Date         : 2015/11/20
** Description  : 添加註釋(http://www.jellythink.com/archives/132)
*/

#include <iostream>
using namespace std;

/*
**  實現(顏料)
*/
class Implementor
{
public:
    virtual void OperationImpl() = 0;
};

/*
**  具體實現(黃色顏料、綠色顏料、藍色顏料)
*/
class ConcreteImpementor : public Implementor
{
public:
    void OperationImpl()
    {
        cout << "OperationImpl" << endl;
    }
};

/*
**  抽象(平面圖形)
**  維護一個指向具體實現的指針(黃色顏料、綠色顏料、藍色顏料)
*/
class Abstraction
{
public:
    Abstraction(Implementor *pImpl) : m_pImpl(pImpl){}
    virtual void Operation() = 0;
protected:
    Implementor *m_pImpl;
};

/*
**  被提煉的抽象(圓形、正方形、長方形)
*/
class RedfinedAbstraction : public Abstraction
{
public:
    RedfinedAbstraction(Implementor *pImpl) : Abstraction(pImpl){}
    void Operation()
    {
        m_pImpl->OperationImpl();
    }
};

int main(void)
{
    Implementor *pImplObj = new ConcreteImpementor();
    Abstraction *pAbsObj = new RedfinedAbstraction(pImplObj);

    pAbsObj->Operation();

    delete pImplObj;
    pImplObj = NULL;

    delete pAbsObj;
    pAbsObj = NULL;

    return 0;
}

詳情參見下文:

Jelly Young:C++設計模式——橋接模式

觀察者模式

1、觀察者模式:定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。當一個對象發生了變化,關注它的對象就會得到通知;這種交互也稱爲發佈-訂閱(publish-subscribe)。目標是通知的發佈者,它發出通知時並不需要知道誰是它的觀察者。(《設計模式:可複用面向對象軟件的基礎》)

2、UML類圖
UML類圖

3、觀察這模式調用時序圖
觀察這模式調用時序圖

4、代碼實例:(引用原文代碼,只是添加註釋)

/*
** FileName     : ObserverPatternDemo
** Author       : Jelly Young
** Date         : 2014/2/14
** Description  : More information (http://www.jellythink.com/archives/359)
** Author       : Aidan Dai
** Date         : 2015/11/21
** Description  : 添加註釋(Aidan Dai)
*/

#include <iostream>
#include <list>
using namespace std;

//觀察者抽象類接口(Aidan Dai)
class Observer
{
public:
    virtual void Update(int) = 0;
};

//訂閱者抽象類接口(Aidan Dai)
class Subject
{
public:
    virtual void Attach(Observer *) = 0;
    virtual void Detach(Observer *) = 0;
    virtual void Notify() = 0;
};

//觀察者抽象類接口實現1(Aidan Dai)
class ConcreteObserver : public Observer
{
public:
    //觀察訂閱者抽象類接口的實現(Aidan Dai)
    ConcreteObserver(Subject *pSubject) : m_pSubject(pSubject){}

    //記錄訂閱者抽象類接口的實現的變化(Aidan Dai)
    void Update(int value)
    {
        cout << "ConcreteObserver get the update. New State:" << value << endl;
    }

private:
    //維護的訂閱者抽象類接口的實現(Aidan Dai)
    Subject *m_pSubject;
};

//觀察者抽象類接口實現2(Aidan Dai)
class ConcreteObserver2 : public Observer
{
public:
    ConcreteObserver2(Subject *pSubject) : m_pSubject(pSubject){}

    void Update(int value)// 響應變更(Aidan Dai)
    {
        cout << "ConcreteObserver2 get the update. New State:" << value << endl;
    }

private:
    Subject *m_pSubject;
};

//訂閱者抽象類接口實現(Aidan Dai)
class ConcreteSubject : public Subject
{
public:
    void Attach(Observer *pObserver);//添加變更(隊列)(Aidan Dai)
    void Detach(Observer *pObserver);//移除已響應變更(Aidan Dai)
    void Notify();// 通過變更隊列指揮觀察者響應變更(Aidan Dai)

    void SetState(int state)//變更(Aidan Dai)
    {
        m_iState = state;
    }

private:
    std::list<Observer *> m_ObserverList;// 變更隊列(Aidan Dai)
    int m_iState;
};

void ConcreteSubject::Attach(Observer *pObserver)
{
    m_ObserverList.push_back(pObserver);// push_back() : insert element at end(Aidan Dai)
}

void ConcreteSubject::Detach(Observer *pObserver)
{
    m_ObserverList.remove(pObserver);// romve() : erase each element matching _Val(Aidan Dai)
}

void ConcreteSubject::Notify()
{
    std::list<Observer *>::iterator it = m_ObserverList.begin();
    while (it != m_ObserverList.end())
    {
        (*it)->Update(m_iState);
        ++it;
    }
}

int main()
{
    // Create Subject
    ConcreteSubject *pSubject = new ConcreteSubject();

    // Create Observer
    Observer *pObserver = new ConcreteObserver(pSubject);
    Observer *pObserver2 = new ConcreteObserver2(pSubject);

    /* original article

    // Change the state
    pSubject->SetState(2);

    // Register the observer
    pSubject->Attach(pObserver);
    pSubject->Attach(pObserver2);

    pSubject->Notify();

    // Unregister the observer
    pSubject->Detach(pObserver);

    // Change the state
    pSubject->SetState(3);

    pSubject->Notify();

    */

    // Subject should register the Observer at first ! but without change, it would be waste of memory.( Aidan Dai )

    // Register the observer
    pSubject->Attach(pObserver);
    pSubject->Attach(pObserver2);

    // Change the state
    pSubject->SetState(2);

    pSubject->Notify();


    delete pObserver;
    delete pObserver2;
    delete pSubject;
}

詳情參見下文:

Jelly Young:C++設計模式——觀察者模式

MV*架構模式

通過以上的學習,現在對面向對象又有了點新的認識!最經典的依舊是面向對象中的封裝、繼承和多態;分清楚什麼關係是is a,什麼是has a,也就時要遵循面向對象的設計原則。

就像《我給媳婦解釋設計模式:第一部分》文中所說的一樣,設計模式的產生是先有問題場景,再基於需求和情景不斷演化設計方案,最後把一些方案標準化成“模式”,要理解設計模式還學結合生活中的實力加以分析和運用,但不斷的實戰中加深對那些經典的設計模式的理解!今天又一次站在了巨人的肩膀上看對象,希望有一天能造個好的對象!

學習了這麼多,還是趕快進入正題題吧!

MVC

早在上個世紀70年代,美國的施樂公司(Xerox)的工程師研發了Smalltalk編程語言,並且開始用它編寫圖形界面的應用程序。而在Smalltalk-80這個版本的時候,一位叫Trygve Reenskaug的工程師設計了MVC圖形應用程序的架構模式,極大地降低了圖形應用程序的管理難度。而在四人幫(GoF)的設計模式當中並沒有把MVC當做是設計模式,而僅僅是把它看成解決問題的一些類的集合。Smalltalk-80 MVC和GoF描述的MVC是最經典的MVC模式。

1、MVC的依賴關係

MVC的依賴關係

2、MVC的調用關係

MVC的依賴關係

MVC Model [1|2]

1、MVC Model 1 和 MVC Model 2的調用關係
MVC Model 1 and MVC Model 2

2、基於Thinkphp來理解MVC Model 2

  • (1) browser->controller->view->browser

第1步是顯而易見的,就像我們現在的團隊網站,但你訪問時www.lsgogroup.com時實際上是訪問www.lsgogroup.com/index.php?s=/Home/Index/index.html,也就是Home模塊下的IndexController的index成員(這是個例外,此時直接1->3->5);由此看來第二步和第四步是可以沒有的,此時第Controller層僅僅只是路由作用,當然也有可能有些邏輯處理(處理路由)

  • (1) browser->controller->model->(data source->controller->)view->browser

第1步是顯而易見的,就像我們現在的團隊網站,但你訪問時http://www.lsgogroup.com/index.php?s=/Blog/Index/index.html時,也就是Blog模塊下的IndexController的index成員;此時Controller層只是不僅起路由作用,還要獲取model層的數據,去渲染view層

個人認爲Thinkphp更傾向於MVP架構模式,只是個人愚見,歡迎大家交流討論。。。

MVP

  • MVP模式有兩種:
    1、MVP(Passive View)
    2、MVP(Supervising Controller)
MVP(Passive View)
MVP(Passive View)的依賴關係

MVP(Passive View)的依賴關係

MVP(Passive View)的調用關係

MVP(Passive View)的調用關係

MVP(Supervising Controller)
MVP(Supervising Controller)的依賴和調用關係

MVP(Supervising Controller)的依賴和調用關係

MVVM

  • MVVM代表的是Model-View-ViewMode(第一次聽說時,小白犯錯了)

MVVM的依賴和調用關係

結束語:

在本次學習中,自己只是結合大神們的原創總結了下,記錄了重點,也可以說是思維導圖吧!方便小白們學習,請大神們原諒我的盜圖,再此感謝原創博主們爲此付出的努力,對他們的分享精神致已崇高的敬意!

於大連個人心路旅程

理想是豐滿的,現實是骨感的。經過,闖過,纔會真正的明白這句話後面的意味。現在在連二線城市都算不上的呼和浩特,幹着自己算不上非常喜歡的工作,還好,還是自己喜歡的圈子,還能做自己喜歡的事情。離家也不遠(180KM),每個星期都可以回去看看年邁的父母,儘儘孝心,有時候想想,這也不錯哦。

外面花花的世界,對我還是有非常大的誘惑,有顆不安分的心,還有熱血在流淌着,但現實是我快當爸爸了;有時候不敢想,如果我去了北京工作,她和我的小baby還在千里之外的家裏,那是一種什麼樣的感覺。

理想還是要有的,萬一實現了呢,你說呢!!!

本文參考以下博文:

1、我是怎樣教媳婦面向對象編程的
2、我給媳婦解釋設計模式:第一部分
3、於大連:C++設計模式——橋接模式
4、於大連:C++設計模式——觀察者模式
5、戴嘉華:界面之下:還原真實的MV*模式
6、阮一峯:談談MVC模式
7、阮一峯:MVC,MVP 和 MVVM 的圖示

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章