• 用户界面与业务逻辑的分离


    界面与逻辑
    基本程序架构一般包含:
    用户界面模块(UI)
      接受用户输入及呈现数据
    业务逻辑模块(Business Logic)
      根据用户需求处理数据

    用户界面与业务逻辑如何交互?

    基本设计原则
    功能模块之间需要进行解耦
    核心思想:强内聚,弱耦合
    -每个模块应该只实现单一的功能
    -模块内部的子模块只为整体的单一功能而存在
    -模块之间通过约定好的接口进行交互

     

     

     

     QCalculatorUI(接收用户的输入,并呈现最终的结果)和QCalculatorDec(实现计算器的核心算法)这两个类没有什么关系,都依赖于顶层的接口ICalculator

    QCalculator的作用就是将QCalculatorUI和QCalculatorDec这两个类通过接口ICalculator结合在一起。

    现在需要做的就是定义一个接口,并且定义一个QCalculator这个类

    在C++中没有接口的概念,但是我们可以通过纯虚类来进行实现。

    ICalculator.h

    #ifndef _ICALCULATOR_H
    #define _ICALCULATOR_H
    
    #include <QString>
    
    class ICalculator
    {
    public:
        virtual bool expression(const QString& exp) = 0;  //接收用户输入
        virtual QString result() = 0;                     //呈现输出结果
    };
    
    
    #endif // ICALCULATOR_H

    添加QCalculaor.h类

    #ifndef QCALCULATOR_H
    #define QCALCULATOR_H
    
    #include"QCalculatorUI.h"
    #include "QCalculatorDec.h"
    
    class QCalculator
    {
    protected:
        QCalculatorUI* m_ui; //UI这个类使用的是二阶构造来构造的,如果有一个成员变量它使用的是二阶构造来完成的,使用该成员变量整体的类也需要使用二阶构造。
        QCalculatorDec m_cal;
    
        QCalculator();
        bool construct();
    public:
        static QCalculator* NewInstance();
        void show();//用来调用UI的show函数
    
        ~QCalculator();
    
    };
    
    #endif // QCALCULATOR_H
    #include "QCalculator.h"
    
    QCalculator::QCalculator()
    {
    
    }
    
    bool QCalculator::construct()
    {
        m_ui = QCalculatorUI::NewInstance();
    
        return (m_ui != NULL);
    }
    
    QCalculator* QCalculator::NewInstance()
    {
        QCalculator* ret = new QCalculator();
    
        if((ret == NULL) || !ret->construct() )
        {
            delete ret;
            ret = NULL;
        }
    
        return ret;
    }
    
    void QCalculator::show()
    {
        m_ui->show();
    }
    
    QCalculator::~QCalculator()
    {
        delete m_ui;
    }

    上面仅仅是添加了两个类,并没有实现QCalculatorUI对IQCalculator的依赖,下面来做这件事。

    实现UI与接口的关联

    #ifndef _QCALCULATORUI_H_
    #define _QCALCULATORUIH_
    
    #include <QWidget>
    #include <QPushButton>
    #include <QLineEdit>
    #include "iCalculator.h"
    
    class QCalculatorUI : public QWidget
    {
        Q_OBJECT
    private:
        QLineEdit* m_edit;
        QPushButton* m_buttons[20];
        ICalculator* m_cal;
    
        QCalculatorUI();
        bool construct();
    private slots:
        void onButtonClicked();
    
    public:
        static QCalculatorUI* NewInstance();
        void show();
        ~QCalculatorUI();
        void setCalculator(ICalculator* cal);
        ICalculator* getCalculator();
    
    };
    
    #endif // _QCALCULATORUI_H_

    QCalculatorUI.cpp

    #include "QCalculatorUI.h"
    #include <QDebug>
    
    QCalculatorUI::QCalculatorUI(): QWidget(NULL,Qt::WindowCloseButtonHint) //此处QCalculatorUI就是作为顶层窗口存在的,虽然这个地方继承自QWidget,但是赋值为NULL,相当于它是没有父类的(但是实际上还是有的)。
                                                                            //将窗口中的最大化和最小化去掉
    {
        //因为QLineEdit与QCalculatorUI以及QPushButton与QCalculatorUI是组合关系,那么就应该同生死,因此需要在构造函数对其定义。因为此处涉及到在堆上申请内存空间,因此需要
        //使用二阶构造
        m_cal = NULL;
    
    }
    
    bool QCalculatorUI::construct()
    {
        bool ret = true;
        const char* btnText[20] =
        {
            "7", "8", "9", "+", "(",
            "4", "5", "6", "-", ")",
            "1", "2", "3", "*", "<-",
            "0", ".", "=", "/", "C",
        };
    
        m_edit = new QLineEdit(this);
    
        if(m_edit != NULL)
        {
            m_edit->move(10,10);
            m_edit->resize(240,30);
            m_edit->setReadOnly(true);  //使QLineEdit只读
            m_edit->setAlignment(Qt::AlignRight); //使字符串靠右对齐
        }
        else
        {
            ret = false;
        }
    
        for(int i=0; (i<4) && ret; i++)
        {
            for(int j=0; (j<5) && ret; j++)
            {
                if(m_buttons[i*5 + j] != NULL)
                {
                    m_buttons[i*5 + j] = new QPushButton(this);
                    m_buttons[i*5 + j]->move(10 + (10 + 40)*j, 50 + (10 + 40)*i);
                    m_buttons[i*5 + j]->resize(40,40);
                    m_buttons[i*5 + j]->setText(btnText[i*5 + j]);
                    connect(m_buttons[i*5 + j],SIGNAL(clicked()), this, SLOT(onButtonClicked()));
                }
                else
                {
                    ret = false;
                }
            }
        }
    
        return ret;
    }
    
    QCalculatorUI* QCalculatorUI::NewInstance()
    {
        QCalculatorUI* ret = new QCalculatorUI();
    
        if((ret == NULL) || !(ret->construct()))
        {
            delete ret;
            ret = NULL;
        }
    
        return ret;
    }
    
    void QCalculatorUI::onButtonClicked()
    {
        QPushButton* btn = dynamic_cast<(QPushButton*)>(sender());
        QString clickText = btn->text();
    
        if(btn !=NULL)
        {
            if(clickText == "<-")//此时应该将字符串的最后一个字符去掉。
            {
                QString text = m_edit->text();
    
                if(text.length() > 0)
                {
                    text.remove(text.length()-1,1);
                    m_edit->setText(text);
                }
            }
            else if(clickText == "C")
            {
                m_edit->setText( "");
            }
            else if(clickText == "=")
            {
                if(m_cal != NULL)
                {
                    m_cal->expression(m_edit->text());
                    m_edit->setText(m_cal->result());
                }
            }
            else
            {
                m_edit->setText(m_edit->text() + clickText);
            }
        }
    
    }
    void QCalculatorUI::show()
    {
        QWidget::show();
        this->setFixedSize(this->width(),this->height()); //固定窗口的大小
    }
    QCalculatorUI::~QCalculatorUI()
    {
    
    }
    
    void QCalculatorUI:: setCalculator(ICalculator* cal)
    {
        m_cal = cal;
    }
    ICalculator* QCalculatorUI::getCalculator()
    {
        return m_cal;
    }

    实现核心算法与接口的关联

    因为在QCalculatorDec.h中已经实现了result和expression函数,因此只需要将QCalculatorDec这个类继承于ICalculator这个类就行。

    如何将UI与核心算法进行间接关联呢?

    #include "QCalculator.h"
    
    QCalculator::QCalculator()
    {
    
    }
    
    bool QCalculator::construct()
    {
        m_ui = QCalculatorUI::NewInstance();
    
        if(m_ui != NULL)
        {
            m_ui->setCalculator(&m_cal);   //将UI和核心算法关联在一起了,这样的关联是通过接口进行的。从代码上看,
                                           //UI与算法并没有产生直接的关系。
        }
    
        return (m_ui != NULL);
    }
    
    QCalculator* QCalculator::NewInstance()
    {
        QCalculator* ret = new QCalculator();
    
        if((ret == NULL) || !ret->construct() )
        {
            delete ret;
            ret = NULL;
        }
    
        return ret;
    }
    
    void QCalculator::show()
    {
        m_ui->show();
    }
    
    QCalculator::~QCalculator()
    {
        delete m_ui;
    }

    小结:

  • 相关阅读:
    Flash P2P 对象复制详解[转]
    解决flashbuilder控制台无输出一例
    评论:工程师们,不要想一辈子靠技术混饭吃[转]
    flashdevelop使用svn
    actionscript中this和super的指向问题
    使用Apparat框架优化你的Flash[转]
    robotlegs【转】
    Flash Player和Adobe AIR内部的垃圾回收机制[转]
    away3d4.0 基础demo一则
    使用JDBC进行批处理
  • 原文地址:https://www.cnblogs.com/-glb/p/12114490.html
Copyright © 2020-2023  润新知