设计模式,以避免不必要地添加抽象函数以适应新功能

design pattern to avoid unnecessary addition of abstract functions to accommodate new functionality

本文关键字:抽象函数 添加 新功能 不必要 设计模式      更新时间:2023-10-16

在下面的代码中,我有抽象类TestAlgModule我将向库用户公开,他们可以使用多种功能,例如VOLUME, MIXER等。但是,假设用户需要一个仅在MixerManager中添加的新函数,那么我需要TestAlgModule抽象类中添加它,现在突然所有派生类都需要添加它而没有任何好处。

如何避免这种情况?

#include <iostream>                                                                                                                                                                                        
using namespace std;                                                                                                                                                                                       
enum {VOLUME, MIXER, UNKNONWN};                                                                                                                                                                            
class TestAlgModule {                                                                                                                                                                                      
public:                                                                                                                                                                                                    
virtual void open(int type) = 0;                                                                                                                                                                       
virtual void close(int type) = 0;                                                                                                                                                                      
};                                                                                                                                                                                                         
class volumeManager : public TestAlgModule                                                                                                                                                                 
{                                                                                                                                                                                                          
public:                                                                                                                                                                                                    
void open(int type) {}                                                                                                                                                                                 
void close(int type) {}                                                                                                                                                                                
};                                                                                                                                                                                                         
class mixerManager : public TestAlgModule                                                                                                                                                                  
{                                                                                                                                                                                                          
public:                                                                                                                                                                                                    
void open(int type) {}                                                                                                                                                                                 
void close(int type) {}                                                                                                                                                                                
void differentFunction() {};                                                                                                                                                                           
};                                                                                                                                                                                                         
/* users calls this to get algModule and then call functions to get the job done */                                                                                                                                                                                         
TestAlgModule *getTestAlgModule(int type) {                                                                                                                                                                
switch(type) {                                                                                                                                                                                         
case VOLUME:                                                                                                                                                                                       
return new volumeManager();                                                                                                                                                                    
case MIXER:                                                                                                                                                                                        
return new mixerManager();                                                                                                                                                                     
default:                                                                                                                                                                                           
break;                                                                                                                                                                                         
}                                                                                                                                                                                                      
return nullptr;                                                                                                                                                                                        
}                                                                                                                                                                                                          
int main() {                                                                                                                                                                                               
TestAlgModule * test = getTestAlgModule(MIXER);                                                                                                                                         
test->open();     
//test->differentFunction();          this can't be called as it is not part of abstract class and users are exposed only abstract class                                                                                                                                                              
return 0;                                                                                                                                                                                              
}                     

如果有什么不清楚的地方,请告诉我,我会尽力回答。我正在寻找一种更好的方法来做到这一点,即VolumeManager的变化应该独立于MixerManager

如果你想使用抽象工厂,就像你在上面的代码中所做的那样,那么你需要返回一个指向基类的指针。这是正确的。然后你需要通过基指针调用所有函数。

顺便说一下,请不要使用原始指针。请改用std::unique指针。

有两种可能的解决方案。

将接口函数作为非纯函数但仍然是虚函数添加到基类中,并具有默认行为。

virtual void differentFunction() {}

由于其他纯函数,基类仍然是抽象的。这可能会导致胖接口。但在许多情况下,这是一个可以接受的解决方案。

第二种可能性是将基类指针向下转换为所需的指针,使用dynamic_cast并检查动态强制转换的返回值。

if(mixerManager* mm = dynamic_cast<mixerManager*>(test)) {
mm->differentFunction();
}

当然,所有这些都取决于整体设计和您想要实现的目标。但以上 2 种是标准模式。

还有其他设计模式可能适合您的需求,例如构建器或原型。请检查。