有这么一种情况,比如在一个类A中,会用到另外一个类B,但是在类B中,也会用到类中的方法。这种情况下,就可能会出现相互包含的情况,在类A中要包含对类B的引用,在类B中又会用到类A的引用,出现了互相包含的情况。
在我的经验中,大概有这么三种处理方式,能够避免互相依赖的情况出现。
举个例子,有如下这样的界面:
假如界面类用Widget表示,安装和卸载的操作均在类FileOper中实现,在FileOper处理的过程中,需要把进度通知到界面上,那么在设计上,就会出现Widget类中用到FileOper的定义,二在FileOper中有要用到Widget的progress控件,这样就出现了相互依赖的情况。
- 用Qt的信号槽去实现,直接发信号通知界面类就可以,这种实现很简单,利用Qt本身支持的方法,但是如果连接比较多,也会在一定 程度上影响效率,具体实现如下:
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private slots:
void onProgress(float);
void onBtnInstall()
{
FileOperSignal fileSignal;
connect(&fileSignal,&FileOperSignal::progress,this,&Widget::onProgress);
fileSignal.install();
}
void onBtnUninstall()
{
FileOperSignal fileSignal;
connect(&fileSignal,&FileOperSignal::progress,this,&Widget::onProgress);
fileSignal.install();
}
private:
Ui::Widget *ui;
};
class FileOperSignal
{
Q_OBJECT
public:
explicit FileOperSignal(const QString& program);
~FileOperSignal();
void install()
{
//do progress
float index;
emit progress(index);
}
void uninstall()
{
//do progress
float index;
emit progress(index);
}
signals:
void progress(float);
};
- 回调函数实现,如果将函数地址最为变量,在FileOper中处理进度时,调用回调函数实现界面的更新,具体的代码如下:
class FileOperCallBack
{
typedef void(*pCallBack)(float);
public:
explicit FileOperCallBack(const QString& program, pCallBack* callback);
~FileOperCallBack();
void install()
{
float progress = 0.0;
for(auto item : m_list)
{
//do function for each file
m_callback(progress);
}
}
void uninstall();
private:
pCallBack m_callback;
QList<QString> m_list;
};
- 依赖导致原则,设计模式中的一种方式,利用多重继承和接口实现,定义一个IProgress的接口,添加一个DoProgress的虚接口,将界面类Widget 继承自IProgress,并在Widget类中实现DoProgress的方法,具体的代码如下:
class IProgress
{
public:
virtual void DoProgress(float)=0;
};
class Widget : public QWidget,public IProgress
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
virtual void DoProgress();
private slots:
void onProgress(float);
void onBtnInstall();
void onBtnUninstall();
private:
Ui::Widget *ui;
};
class FileOperInterface
{
public:
explicit FileOperInterface(const QString& program,IProgress* progress);
~FileOperInterface();
void install()
{
//do the function
float progress = 0.0;
if(m_progress != nullptr)
m_progress->DoProgress(progress);
}
private:
IProgress* m_progress;
};