学习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 的图示

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值