用戶界面與業務邏輯的分離


界面與邏輯
基本程序架構一般包含:
用戶界面模塊(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; }

小結:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM