C++设计模式-开放-封闭原则基本概念与实例

目录

 

基本概念

举一个例子


基本概念

在如那就的设计模式中,不能修改,但可以扩展的实现是一条十分重要的原则,它是开放-封闭原则(The Open-Clossed Principle,简称OCP)或开-关闭原则;

开放-封闭原则,软件实体(类、模块、函数等)应该可以扩展,但不能修改。【ASD】

对于扩展是开放的(Open for extension),对于更改是封闭的(Closed for modification)【ASD】

【注意】不要指望在系统一开始时需求确定,就不会变化了,这是不科学的想法,,既然需求是会变化的,那么如何在面对需求变化时,设计软件可以相对容易的修改,不至于新系统一来,老系统推倒。


设计软件时,要时时刻刻的考虑,尽量让这个类足够好,写好就不要去修改了,但新需求来了,增加一些类就完事了,原理的代码则不能动。

无论模板是多么的封闭,都会存在一些无法对之封闭的变化。既然不能完全封闭,设计人员必须对于他设计的模块应该对哪些变化封闭做出选择。他必须先猜出最有可能发送变化的种类,然后构造抽象来隔离那些变化【ASD】

在最初写代码的时候,假设变化不会发生。当变化发生时,我们创建抽象来隔离以后发送的同类变化【ASD】。


【总结】
开放-封闭原则是面向对象设计的核心所在。遵循这个原则可以带来面向对象技术所声明的巨大好处,也就是可维护、可扩展、可复用、灵活性好。开发人员应该仅对程序中呈现出频繁变化的哪些部分做出抽象,然而,对于应用程序中每个部分都刻意的进行抽象同样不是一个好主意。拒绝不成熟的抽象和抽象本身一样重要【ASD】。

 

举一个例子

做一个计算器啥的!

目录结构如下:

C++设计模式-开放-封闭原则基本概念与实例

 

UML图如下:

C++设计模式-开放-封闭原则基本概念与实例

程序运行截图如下:

C++设计模式-开放-封闭原则基本概念与实例

源码如下:

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;
    }
}