当前位置:网站首页>QT learning 15 separation of user interface and business logic
QT learning 15 separation of user interface and business logic
2022-06-29 11:36:00 【A little black sauce】
Qt Study 15 Separation of user interface and business logic
Interface and logic
- Basic program architecture Generally including :
- User interface module (UI)
- Accept user input and present data
- Business logic modular (Business Logic)
- Process data according to user needs
- User interface module (UI)
problem
The user interface And Business logic how Interaction ?
Basic design principles
Function module Need to be decoupled
The core idea : High cohesion , Low coupling
- Each module should implement only Single function
- Internal to the module Sub modules exist only for a single function of the whole
- Between modules Interact through the agreed interface
In engineering development What is the interface ?
- In a broad sense :
- Interface is A contract ( agreement , grammar , Format, etc. )
- narrow sense :
- Process oriented : Interface is A set of predefined function prototypes
- object-oriented : Interface is Pure virtual class (C# and Java Directly support interfaces )
- In a broad sense :
Interaction between user interface and business logic

Between modules only Through the interface
- There must be a module reuse interface
- There must be an interface corresponding to the module implementation
The relationship between modules is Single dependency Of
- Avoid circular dependencies between modules
- Circular dependency is one of the criteria for bad design
The overall architecture of the calculator application

Code display
ICalculator.h
/* ICalculator.h Interface pure virtual class */
#include "QCalculator.h"
QCalculator::QCalculator() {
}
bool QCalculator::construct() {
m_ui = QCalculatorUI::NewInstance();
if (m_ui != NULL) {
m_ui->setCalculator(&m_cal);
}
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.h
/* QCalculatorUI.h */
#ifndef QCALCULATORUI_H
#define QCALCULATORUI_H
#include <QWidget>
#include <QLineEdit>
#include <QPushButton>
#include "ICalculator.h"
#define SPACE 10
#define LINEEDIT_HEIGHT 45
#define WIDTH 60
#define HEIGHT 60
#define ROW 4
#define COL 5
class QCalculatorUI : public QWidget
{
Q_OBJECT
private:
QLineEdit* m_edit;
QPushButton* m_button[20];
ICalculator* m_cal;
QCalculatorUI();
bool construct();
public:
static QCalculatorUI* NewInstance();
void show();
void setCalculator(ICalculator* cal);
ICalculator* getCalculator();
~QCalculatorUI();
private slots:
void onButtonClicked();
};
#endif // QCALCULATORUI_H
QCalculatorUI.cpp
/* QCalculatorUI.cpp */
#include "QCalculatorUI.h"
#include <QDebug>
QCalculatorUI::QCalculatorUI() : QWidget(NULL, Qt::WindowCloseButtonHint) {
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(SPACE, SPACE);
m_edit->resize(5*WIDTH+4*SPACE, LINEEDIT_HEIGHT);
m_edit->setReadOnly(true);
m_edit->setAlignment(Qt::AlignRight);
}
else {
ret = false;
}
for (int i = 0; (i < ROW) && ret; i++) {
for (int j = 0; (j < COL) && ret; j++) {
m_button[i*COL+j] = new QPushButton(this);
if (m_button[i*COL+j] != NULL) {
m_button[i*COL+j]->resize(WIDTH, HEIGHT);
m_button[i*COL+j]->move(SPACE+(SPACE+WIDTH)*j, SPACE+SPACE+LINEEDIT_HEIGHT+(SPACE+WIDTH)*i);
m_button[i*COL+j]->setText(btnText[i*COL+j]);
connect(m_button[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::show() {
QWidget::show();
this->setFixedSize(this->width(), this->height());
}
void QCalculatorUI::setCalculator(ICalculator *cal) {
m_cal = cal;
}
ICalculator *QCalculatorUI::getCalculator() {
return m_cal;
}
QCalculatorUI::~QCalculatorUI() {
}
void QCalculatorUI::onButtonClicked() {
// Get the sender of the signal
QPushButton* btn = dynamic_cast<QPushButton*>(sender());
if (btn != NULL) {
qDebug() << btn->text();
QString clickText = btn->text();
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);
}
}
}
QCalculatorDec.h
/* QCalculatorDec.h */
#ifndef QCALCULATORDEC_H
#define QCALCULATORDEC_H
#include <QString>
#include <QQueue>
#include <QStack>
#include "ICalculator.h"
class QCalculatorDec : public ICalculator
{
protected:
QString m_result;
bool isDigitOrDot(QChar c);
bool isSymbol(QChar c);
bool isSign(QChar c);
bool isNumber(QString s);
bool isOperator(QString s);
bool isLeft(QString s);
bool isRight(QString s);
int priority(QString s);
bool match(QQueue<QString>& exp);
QString calculate(QQueue<QString>& exp);
QString calculate(const QString& l, const QString& op, const QString& r);
bool transform(QQueue<QString>& exp, QQueue<QString>& output);
QQueue<QString> split(const QString& exp);
public:
QCalculatorDec();
bool expression(const QString& exp);
QString result();
};
#endif // QCALCULATORDEC_H
QCalculatorDec.cpp
/* QCalculatorDec.cpp */
#include "QCalculatorDec.h"
#include <QDebug>
bool QCalculatorDec::isDigitOrDot(QChar c) {
return (('0' <= c) && (c <= '9')) || (c == '.');
}
bool QCalculatorDec::isSymbol(QChar c) {
return isOperator(c) || (c == '(') || (c == ')');
}
bool QCalculatorDec::isSign(QChar c) {
return (c == '+') || (c == '-');
}
bool QCalculatorDec::isNumber(QString s) {
bool ret = false;
s.toDouble(&ret);
return ret;
}
bool QCalculatorDec::isLeft(QString s) {
return (s == "(");
}
bool QCalculatorDec::isRight(QString s) {
return (s == ")");
}
int QCalculatorDec::priority(QString s) {
int ret = 0;
if ((s == '+') || (s == '-')) {
ret = 1;
}
if ((s == '*') || (s == '/')) {
ret = 2;
}
return ret;
}
bool QCalculatorDec::match(QQueue<QString> &exp) {
bool ret = true;
QStack<QString> s;
for (int i = 0; i < exp.length(); i++) {
if (isLeft(exp[i])) {
s.push(exp[i]);
}
else if (isRight(exp[i])) {
if (!s.isEmpty() && isLeft(s.top())) {
s.pop();
}
else {
ret = false;
break;
}
}
}
return ret;
}
QString QCalculatorDec::calculate(QQueue<QString> &exp) {
QString ret = "Error";
QStack<QString> s;
while (!exp.isEmpty()) {
QString e = exp.dequeue();
if (isNumber(e)) {
s.push(e);
}
else if (isOperator(e)) {
QString right = !s.isEmpty() ? s.pop() : "";
QString left = !s.isEmpty() ? s.pop() : "";
QString result = calculate(left, e, right);
if (result != "Error") {
s.push(result);
}
else {
break;
}
}
else {
break;
}
}
if (exp.isEmpty() && s.size() == 1 && isNumber(s.top())) {
ret = s.pop();
}
return ret;
}
QString QCalculatorDec::calculate(const QString &l, const QString &op, const QString &r) {
QString ret = "Error";
if (isNumber(l) && isNumber(r) && isOperator(op)) {
double ld = l.toDouble();
double rd = r.toDouble();
if (op == "+") {
ret.sprintf("%f", ld + rd);
}
else if (op == "-") {
ret.sprintf("%f", ld - rd);
}
else if (op == "*") {
ret.sprintf("%f", ld * rd);
}
else if (op == "/") {
const double P = 0.00000000000000001;
if ((-P < rd) && (rd < P)) {
ret = "Error";
}
else {
ret.sprintf("%f", ld / rd);
}
}
}
return ret;
}
bool QCalculatorDec::transform(QQueue<QString> &exp, QQueue<QString> &output) {
bool ret = match(exp);
QStack<QString> s;
output.clear();
while (!exp.isEmpty()) {
QString e = exp.dequeue();
if (isNumber(e)) {
output.enqueue(e);
}
else if (isOperator(e)) {
while (!s.isEmpty() && priority(e) <= priority(s.top())) {
output.enqueue(s.pop());
}
s.push(e);
}
else if (isLeft(e)) {
s.push(e);
}
else if (isRight(e)) {
while (!s.isEmpty() && !isLeft(s.top())) {
output.enqueue(s.pop());
}
if (!s.isEmpty()) {
s.pop();
}
} else {
ret = false;
}
}
while (!s.isEmpty()) {
output.enqueue(s.pop());
}
if (!ret) {
output.clear();
}
return ret;
}
QQueue<QString> QCalculatorDec::split(const QString &exp) {
QString num = "";
QString pre = "";
QQueue<QString> ret;
for (int i = 0; i < exp.length(); i++) {
if (isDigitOrDot(exp[i])) {
num += exp[i];
pre = exp[i];
}
else if (isSymbol(exp[i])) {
if (num != "") {
ret.enqueue(num);
num.clear();
}
if (isSign(exp[i]) && ((pre == "") || (isLeft(pre)) || (isOperator(pre)))) {
num += exp[i];
}
else {
ret.enqueue(exp[i]);
}
pre = exp[i];
}
}
if (!num.isEmpty()) {
ret.enqueue(num);
}
return ret;
}
bool QCalculatorDec::isOperator(QString s) {
return (s == '+') || (s == '-') || (s == '*') || (s == '/');
}
QCalculatorDec::QCalculatorDec() {
}
bool QCalculatorDec::expression(const QString &exp) {
bool ret = false;
QQueue<QString> spExp = split(exp);
QQueue<QString> postExp;
if (transform(spExp, postExp)) {
m_result = calculate(postExp);
ret = (m_result != "Error");
}
else {
m_result = "Error";
}
return ret;
}
QString QCalculatorDec::result() {
return m_result;
}
QCalculator.h
/* QCalculator.h */
#ifndef QCALCULATOR_H
#define QCALCULATOR_H
#include "QCalculatorUI.h"
#include "QCalculatorDec.h"
class QCalculator
{
protected:
QCalculatorUI* m_ui;
QCalculatorDec m_cal;
QCalculator();
bool construct();
public:
static QCalculator* NewInstance();
void show();
~QCalculator();
};
#endif // QCALCULATOR_H
QCalculatorl.cpp
/* QCalculatorl.cpp */
#include "QCalculator.h"
QCalculator::QCalculator() {
}
bool QCalculator::construct() {
m_ui = QCalculatorUI::NewInstance();
if (m_ui != NULL) {
m_ui->setCalculator(&m_cal);
}
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;
}
main.cpp
/* main.cpp*/
#include <QWidget>
#include <QApplication>
#include "QCalculator.h"
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QCalculator* cal = QCalculator::NewInstance();
int ret = -1;
if (cal != NULL) {
cal->show();
ret = a.exec();
delete cal;
}
return ret;
}
Summary
- The interaction between modules requires Through the interface
- Interface It is a kind of communication between modules in development **“ contract ”**
- Between modules Circular dependencies cannot occur
- Basic design principles : High cohesion , Low coupling
边栏推荐
- QT learning 11 string classes in QT
- Take another picture of cloud redis' improvement path
- 极限导论总结
- CTO专访:合见工软深化产品布局 加速国产EDA技术革新
- Online text filter less than specified length tool
- 【各种**问题系列】OLTP和OLAP是啥?
- 在日本的 IT 公司工作是怎样一番体验?
- MySQL开启慢查询
- X-FRAME-OPTIONS web page hijacking vulnerability
- Course design for the end of the semester: product sales management system based on SSM
猜你喜欢

Qt学习09 计算器界面代码重构

专访 SUSS NiFT 负责人:Web3 的未来离不开“人人为我,我为人人”的治理

What are the main factors that affect the heat dissipation of LED packaging?

CTO专访:合见工软深化产品布局 加速国产EDA技术革新

中国计算语言学大会、全国知识图谱与语义计算大会赛题火热进行中

多线程实现客户端与服务端通信(初级版本)

How to test the performance of container platform, including stability, expansion efficiency and component performance

Take another picture of cloud redis' improvement path

XML外部实体注入漏洞(一)

影响LED封装散热主要因素有哪些?
随机推荐
9 款好用到爆的 JSON 处理工具,极大提高效率!
【HBZ分享】AQS + CAS +LockSupport 实现ReentrantLock的原理
QT learning 11 string classes in QT
Xuetong denies that the theft of QQ number is related to it: it has been reported; IPhone 14 is ready for mass production: four models are launched simultaneously; Simple and elegant software has long
LeetCode 535 TinyURL的加密与解密[map] HERODING的LeetCode之路
matlab基础 max 求一维或二维数组的最大值+sleep(pause)
[daily 3 questions (3)] reformat the phone number
When a technician becomes a CEO, what "bugs" should be modified?
Modbustcp protocol WiFi wireless learning single channel infrared module (small shell version)
The Chinese Computational Linguistics Conference and the national knowledge atlas and Semantic Computing Conference are in full swing
(JS) iterator mode
(JS) array de duplication
Qt学习06 窗口部件及窗口类型
TTL serial port learning infrared remote control module can be extended to network control
Specific method and example program of Siemens s7-200smart control stepping motor
(JS) handwriting depth comparison
直击产业落地!飞桨重磅推出业界首个模型选型工具
Qt学习03 Qt的诞生和本质
【HBZ分享】Mysql的InnoDB原理
How to find out the wrong mobile number when querying MySQL