C++设计模式-开放-封闭原则基本概念与实例
目录
基本概念
在如那就的设计模式中,不能修改,但可以扩展的实现是一条十分重要的原则,它是开放-封闭原则(The Open-Clossed Principle,简称OCP)或开-关闭原则;
开放-封闭原则,软件实体(类、模块、函数等)应该可以扩展,但不能修改。【ASD】
对于扩展是开放的(Open for extension),对于更改是封闭的(Closed for modification)【ASD】
【注意】不要指望在系统一开始时需求确定,就不会变化了,这是不科学的想法,,既然需求是会变化的,那么如何在面对需求变化时,设计软件可以相对容易的修改,不至于新系统一来,老系统推倒。
设计软件时,要时时刻刻的考虑,尽量让这个类足够好,写好就不要去修改了,但新需求来了,增加一些类就完事了,原理的代码则不能动。
无论模板是多么的封闭,都会存在一些无法对之封闭的变化。既然不能完全封闭,设计人员必须对于他设计的模块应该对哪些变化封闭做出选择。他必须先猜出最有可能发送变化的种类,然后构造抽象来隔离那些变化【ASD】
在最初写代码的时候,假设变化不会发生。当变化发生时,我们创建抽象来隔离以后发送的同类变化【ASD】。
【总结】
开放-封闭原则是面向对象设计的核心所在。遵循这个原则可以带来面向对象技术所声明的巨大好处,也就是可维护、可扩展、可复用、灵活性好。开发人员应该仅对程序中呈现出频繁变化的哪些部分做出抽象,然而,对于应用程序中每个部分都刻意的进行抽象同样不是一个好主意。拒绝不成熟的抽象和抽象本身一样重要【ASD】。
举一个例子
做一个计算器啥的!
目录结构如下:
UML图如下:
程序运行截图如下:
源码如下:
operation.h
#ifndef OPERATION_H
#define OPERATION_H
class Operation
{
public:
Operation();
virtual ~Operation();
double getNumberA() const;
void setNumberA(const double number);
double getNumberB() const;
void setNumberB(const double number);
virtual double getResult();
double m_numberA;
double m_numberB;
};
#endif // OPERATION_H
operationfactory.h
#ifndef OPERATIONFACTORY_H
#define OPERATIONFACTORY_H
#include "otheroperation.h"
#include <QString>
class OperationFactory{
public:
static Operation *createOperation(QString operate){
Operation *oper = NULL;
if(operate == "+"){
oper = new OperationAdd;
}
else if(operate == "-"){
oper = new OperationSub;
}
else if(operate == "*"){
oper = new OperationMul;
}
else if(operate == "/"){
oper = new OperationDiv;
}
else{
throw "The opertation is error!";
}
return oper;
}
};
#endif // OPERATIONFACTORY_H
otheroperation.h
#ifndef OTHEROPERATION_H
#define OTHEROPERATION_H
#include <operation.h>
class OperationAdd: public Operation{
public:
double getResult() override;
~OperationAdd();
};
class OperationSub: public Operation{
public:
double getResult() override;
~OperationSub();
};
class OperationMul: public Operation{
public:
double getResult() override;
~OperationMul();
};
class OperationDiv: public Operation{
public:
double getResult() override;
~OperationDiv();
};
#endif // OTHEROPERATION_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
protected slots:
void btnClicked();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
operation.cpp
#include "operation.h"
#include <QDebug>
Operation::Operation()
{
m_numberA = 0.0;
m_numberB = 0.0;
}
Operation::~Operation()
{
qDebug()<< "Operation::~Operation() called";
}
double Operation::getNumberA() const
{
return m_numberA;
}
void Operation::setNumberA(const double number)
{
m_numberA = number;
}
double Operation::getNumberB() const
{
return m_numberB;
}
void Operation::setNumberB(const double number)
{
m_numberB = number;
}
double Operation::getResult()
{
double result = 0.0;
return result;
}
otheroperation.cpp
#include "otheroperation.h"
#include <QDebug>
double OperationAdd::getResult()
{
double result = 0.0;
result = m_numberA + m_numberB;
return result;
}
OperationAdd::~OperationAdd()
{
qDebug()<< "OperationAdd::~OperationAdd() called!";
}
double OperationSub::getResult()
{
double result = 0.0;
result = m_numberA - m_numberB;
return result;
}
OperationSub::~OperationSub()
{
qDebug()<< "OperationSub::~OperationSub() called!";
}
double OperationMul::getResult()
{
double result = 0.0;
result = m_numberA * m_numberB;
return result;
}
OperationMul::~OperationMul()
{
qDebug()<< "OperationMul::~OperationMul() called!";
}
double OperationDiv::getResult()
{
double result = 0.0;
if(m_numberB < 0.0001 )
throw "The denominator cannot be zero";
result = m_numberA / m_numberB;
return result;
}
OperationDiv::~OperationDiv()
{
qDebug()<< "OperationDiv::~OperationDiv() called!";
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "operationfactory.h"
#include <QDebug>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
this->setWindowTitle("**** IT1995");
QStringList list;
list << "+" << "-" << "*" << "/";
ui->operatorComboBox->addItems(list);
connect(ui->pushButton, SIGNAL(clicked(bool)), this, SLOT(btnClicked()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::btnClicked()
{
if(ui->num1LineEdit->text().isEmpty() || ui->num2LineEdit->text().isEmpty())
return;
Operation *oper = NULL;
try{
oper = OperationFactory::createOperation(ui->operatorComboBox->currentText());
oper->setNumberA(ui->num1LineEdit->text().toDouble());
oper->setNumberB(ui->num2LineEdit->text().toDouble());
ui->resultLineEdit->setText(QString::number(oper->getResult()));
}
catch(const char *err){
qDebug()<< err;
}
if(oper != NULL){
delete oper;
}
}